/// <summary>
        ///     Builds the type index, mapping a table reference to its type.
        /// </summary>
        public void BuildVarTypeMap(PapyrusAssemblyDefinition asm, PapyrusMethodDefinition method)
        {
            varTypes.Clear();
            var obj = asm.Types.First();

            foreach (var t in obj.Fields)
            {
                varTypes[t.Name.Value.ToLower()] = t.TypeName;
            }
            foreach (var t in method.Parameters)
            {
                varTypes[t.Name.Value.ToLower()] = t.TypeName.Value;
            }
            foreach (var t in method.GetVariables())
            {
                varTypes[t.Name.Value.ToLower()] = t.TypeName.Value;
            }
        }
예제 #2
0
        public PapyrusReferenceAndConstantValueViewModel(List <PapyrusAssemblyDefinition> loadedAssemblies,
                                                         PapyrusTypeDefinition currentType,
                                                         PapyrusMethodDefinition currentMethod, OpCodeArgumentDescription desc, PapyrusPrimitiveType[] argumentTypes)
        {
            this.loadedAssemblies = loadedAssemblies;
            this.currentType      = currentType;
            this.currentMethod    = currentMethod;
            this.desc             = desc;
            this.argumentTypes    = argumentTypes;

            if (argumentTypes == null)
            {
                argumentTypes = new PapyrusPrimitiveType[0];
            }

            // Update the type constraints so we are only able to assign
            // values of the correct types.
            if (desc != null && argumentTypes.Length > 0)
            {
                UpdateTypeConstraints(argumentTypes);
            }

            if (currentMethod != null)
            {
                var references = new List <PapyrusMemberReference>();
                references.AddRange(currentMethod.Parameters);
                references.AddRange(currentMethod.GetVariables());
                if (currentType != null)
                {
                    references.AddRange(currentType.Fields);
                }

                ReferenceCollection = new ObservableCollection <PapyrusMemberReference>(references);

                HideValueInputs();

                ReferenceValueVisibility = Visibility.Visible;

                //SelectedValueType = ReferenceCollection.LastOrDefault();
            }
            ComboBoxItems     = new ObservableCollection <FrameworkElement>(CreateComboBoxItems());
            SelectedValueType = ComboBoxItems.First() as ComboBoxItem;
        }
 public PapyrusReferenceValueViewModel(List <PapyrusAssemblyDefinition> loadedAssemblies,
                                       PapyrusTypeDefinition currentType, PapyrusMethodDefinition currentMethod, OpCodeArgumentDescription desc)
 {
     this.loadedAssemblies = loadedAssemblies;
     this.currentType      = currentType;
     this.currentMethod    = currentMethod;
     this.desc             = desc;
     if (currentMethod != null)
     {
         ReferenceCollection = new ObservableCollection <PapyrusMemberReference>(currentMethod.GetVariables());
     }
     ComboBoxItems             = new ObservableCollection <FrameworkElement>(CreateComboBoxItems());
     SelectedReferenceType     = ComboBoxItems.First() as ComboBoxItem;
     ReferenceSelectionVisible = Visibility.Visible;
 }
        private void UpdateReferenceCollection(ComboBoxItem value)
        {
            if (currentMethod == null)
            {
                return;
            }
            var tar = value.Content.ToString().ToLower();

            ReferenceSelectionVisible = Visibility.Visible;
            if (tar == "variable")
            {
                var papyrusVariableReferences = currentMethod.GetVariables();
                papyrusVariableReferences.ForEach(i => i.Type = PapyrusPrimitiveType.Reference);
                ReferenceCollection = new ObservableCollection <PapyrusMemberReference>(Filter(papyrusVariableReferences));
            }
            else if (tar == "parameter")
            {
                var papyrusParameterDefinitions = currentMethod.Parameters;
                ReferenceCollection =
                    new ObservableCollection <PapyrusMemberReference>(Filter(papyrusParameterDefinitions));
            }
            else if (tar == "field")
            {
                var papyrusFieldDefinitions = currentType.Fields.ToList();
                ReferenceCollection = new ObservableCollection <PapyrusMemberReference>(Filter(papyrusFieldDefinitions));
            }
            else if (tar == "none")
            {
                if (currentType.Assembly != null)
                {
                    SelectedReference = new PapyrusVariableReference
                    {
                        Name  = "".Ref(currentType.Assembly),
                        Value = null,
                        Type  = PapyrusPrimitiveType.None
                    };
                }
                ReferenceSelectionVisible = Visibility.Collapsed;
            }
            else if (tar == "self")
            {
                if (currentType.Assembly != null)
                {
                    SelectedReference = new PapyrusVariableReference
                    {
                        Name  = "Self".Ref(currentType.Assembly),
                        Value = "Self",
                        Type  = PapyrusPrimitiveType.Reference
                    };
                }
                ReferenceSelectionVisible = Visibility.Collapsed;
            }
            //else if (tar == "selfref")
            //{
            //    if (currentType.Assembly != null)
            //    {
            //        SelectedReference = new PapyrusVariableReference
            //        {
            //            Name = "SelfRef".Ref(currentType.Assembly),
            //            Value = "SelfRef",
            //            Type = PapyrusPrimitiveType.Reference
            //        };
            //    }
            //    ReferenceSelectionVisible = Visibility.Collapsed;
            //}
        }
예제 #5
0
        //private void WriteInstructionConditional(SourceBuilder source, int indent, PapyrusInstruction instruction, PapyrusMethodDefinition method, PapyrusTypeDefinition type, PapyrusAssemblyDefinition asm)
        //{
        //    SetBuilder(source, indent);
        //    var i = instruction;
        //    var boolean = instruction.GetArg(0);
        //    AppendLine("if (" + boolean + ")");
        //}

        //private bool IsJumpf(PapyrusOpCode opCode)
        //{
        //    return opCode == PapyrusOpCode.Jmpf;
        //}
        //private bool IsJumpt(PapyrusOpCode opCode)
        //{
        //    return opCode == PapyrusOpCode.Jmpt;
        //}
        //private bool IsJump(PapyrusOpCode opCode)
        //{
        //    return opCode == PapyrusOpCode.Jmp || opCode == PapyrusOpCode.Jmpf || opCode == PapyrusOpCode.Jmpt;
        //}

        private string WriteInstruction(PapyrusInstruction instruction, PapyrusMethodDefinition method,
                                        PapyrusTypeDefinition type)
        {
            var i = instruction;

            switch (i.OpCode)
            {
            case PapyrusOpCodes.Nop:
            {
                return("// Do Nothing Operator (NOP)");
            }

            case PapyrusOpCodes.Callstatic:
            {
                var comment      = WritePapyrusInstruction(i) + Environment.NewLine;
                var val          = string.Join(",", i.Arguments.Skip(2).Take(i.Arguments.Count - 3).Select(GetArgumentValue));
                var location     = GetArgumentValue(i.Arguments[0]);
                var functionName = GetArgumentValue(i.Arguments[1]);
                var assignee     = GetArgumentValue(i.Arguments.LastOrDefault());

                var args =
                    string.Join(",", val, string.Join(",", i.OperandArguments.Select(GetArgumentValue))).Trim(',');

                if (assignee != null)
                {
                    assignee += " = ";
                    if (assignee.ToLower().Contains("::nonevar"))
                    {
                        assignee = string.Empty;
                    }
                }
                return(comment + assignee + (location + ".").Replace("self.", "") + functionName + "(" + args + ");");
            }

            case PapyrusOpCodes.Callmethod:
            {
                var comment = WritePapyrusInstruction(i) + Environment.NewLine;

                var val          = string.Join(",", i.Arguments.Skip(2).Take(i.Arguments.Count - 3).Select(GetArgumentValue));
                var location     = GetArgumentValue(i.Arguments[1]);
                var functionName = GetArgumentValue(i.Arguments[0]);
                var assignee     = GetArgumentValue(i.Arguments.LastOrDefault());

                var args =
                    string.Join(",", val, string.Join(",", i.OperandArguments.Select(GetArgumentValue))).Trim(',');

                if (assignee != null)
                {
                    assignee += " = ";
                    if (assignee.ToLower().Contains("::nonevar"))
                    {
                        assignee = string.Empty;
                    }
                }

                return(comment + assignee + (location + ".").Replace("self.", "") + functionName + "(" + args + ");");
            }

            case PapyrusOpCodes.Return:
            {
                var comment = WritePapyrusInstruction(i) + Environment.NewLine;

                string val;
                var    firstArg    = GetArgumentValue(i.Arguments.FirstOrDefault());
                var    firstVarArg = GetArgumentValue(i.OperandArguments.FirstOrDefault());
                if (firstArg != null)
                {
                    val = " " + firstArg;
                }
                else if (firstVarArg != null)
                {
                    val = " " + firstVarArg;
                }
                else
                {
                    val = "";
                }

                return(comment + ("return" + val).Trim() + ";");
                //WritePapyrusInstruction(i);
            }

            case PapyrusOpCodes.Assign:
            {
                var comment = WritePapyrusInstruction(i) + Environment.NewLine;

                var val1 = GetArgumentValue(i.Arguments.FirstOrDefault());
                var val2 = GetArgumentValue(i.Arguments.LastOrDefault());
                var val3 = GetArgumentValue(i.OperandArguments.FirstOrDefault());
                var val4 = GetArgumentValue(i.OperandArguments.LastOrDefault());

                var var0 = val1 ?? val3;
                var var1 = val2 ?? val4;
                if (string.IsNullOrEmpty(var1))
                {
                    return(var0 + " = null;");
                }
                return(comment + var0 + " = " + var1 + ";");
            }

            case PapyrusOpCodes.ArrayRemoveElements:
            {
                var comment = WritePapyrusInstruction(i) + Environment.NewLine;

                var array = GetArgumentValue(i.Arguments[0]);
                var index = GetArgumentValue(i.Arguments[1]);
                var count = GetArgumentValue(i.Arguments[2]);

                return(comment + "Array.RemoveItems(" + array + ", " + index + ", " + count + ");");
            }

            case PapyrusOpCodes.ArrayFindElement:
            {
                var comment = WritePapyrusInstruction(i) + Environment.NewLine;

                var array         = GetArgumentValue(i.Arguments[0]);
                var destination   = GetArgumentValue(i.Arguments[1]);
                var elementToFind = GetArgumentValue(i.Arguments[2]);
                var startIndex    = GetArgumentValue(i.Arguments[3]);

                return(comment + destination + " = Array.IndexOf(" + array + ", " + elementToFind + ", " +
                       startIndex + ");");
            }

            case PapyrusOpCodes.ArrayFindStruct:
            {
                var comment = WritePapyrusInstruction(i) + Environment.NewLine;

                var array        = GetArgumentValue(i.Arguments[0]);
                var destination  = GetArgumentValue(i.Arguments[1]);
                var fieldToMatch = GetArgumentValue(i.Arguments[2]);
                var value        = GetArgumentValue(i.Arguments[3]);
                var startIndex   = GetArgumentValue(i.Arguments[4]);

                return(comment + destination + " = Structs.IndexOf(" + array + ", " + fieldToMatch + ", " + value +
                       ", " + startIndex + ");");
            }

            case PapyrusOpCodes.PropGet:
            {
                var comment = WritePapyrusInstruction(i) + Environment.NewLine;

                var property  = GetArgumentValue(i.Arguments[0]);
                var owner     = GetArgumentValue(i.Arguments[1]);
                var targetVar = GetArgumentValue(i.Arguments[2]);

                return(comment + targetVar + " = " + owner + "." + property + ";");
            }

            case PapyrusOpCodes.PropSet:
            {
                var comment = WritePapyrusInstruction(i) + Environment.NewLine;

                var property = GetArgumentValue(i.Arguments[0]);
                var owner    = GetArgumentValue(i.Arguments[1]);
                var value    = GetArgumentValue(i.Arguments[2]);


                return(comment + owner + "." + property + " = " + value + ";");
            }

            case PapyrusOpCodes.StructSet:
            {
                var structVar   = GetArgumentValue(i.Arguments[0]);
                var structField = GetArgumentValue(i.Arguments[1]);
                var value       = GetArgumentValue(i.Arguments[2]);
                return(structVar + "." + structField + " = " + value + ";");
                // (value + "." + structField + " = " + structVar + "." + structField + ";");
            }

            case PapyrusOpCodes.StructGet:
            {
                var asignee     = GetArgumentValue(i.Arguments[0]);
                var structVar   = GetArgumentValue(i.Arguments[1]);
                var structField = GetArgumentValue(i.Arguments[2]);
                return(asignee + " = " + structVar + "." + structField + ";");
            }

            case PapyrusOpCodes.ArraySetElement:
            {
                var array = GetArgumentValue(i.Arguments[0]);
                var index = GetArgumentValue(i.Arguments[1]);
                var value = GetArgumentValue(i.Arguments[2]);
                return(array + "[" + index + "] = " + value + ";");
            }

            case PapyrusOpCodes.ArrayGetElement:
            {
                var asignee = GetArgumentValue(i.Arguments[0]);
                var array   = GetArgumentValue(i.Arguments[1]);
                var index   = GetArgumentValue(i.Arguments[2]);
                return(asignee + " = " + array + "[" + index + "];");
            }

            case PapyrusOpCodes.ArrayLength:
            {
                var asignee = GetArgumentValue(i.Arguments[0]);
                var array   = GetArgumentValue(i.Arguments[1]);
                return(asignee + " = " + array + ".Length;");
            }

            case PapyrusOpCodes.ArrayCreate:
            {
                var asignee     = GetArgumentValue(i.Arguments[0]);
                var size        = GetArgumentValue(i.Arguments[1]);
                var possibleVar =
                    method.GetVariables().FirstOrDefault(v => v.Name.Value == asignee);
                var field = type.Fields.FirstOrDefault(v => v.Name.Value == asignee);
                var prop  = type.Properties.FirstOrDefault(v => v.Name.Value == asignee);
                if (possibleVar != null)
                {
                    return(asignee + " = new " + possibleVar.TypeName.Value.Replace("[]", "") + "[" + size + "];");
                }
                if (field != null)
                {
                    return(asignee + " = new " + field.TypeName.Replace("[]", "") + "[" + size + "];");
                }
                if (prop != null)
                {
                    return(asignee + " = new " + prop.TypeName.Value.Replace("[]", "") + "[" + size + "];");
                }
            }
            break;

            case PapyrusOpCodes.Strcat:
            {
                var asignee = GetArgumentValue(i.Arguments[0]);
                var str     = GetArgumentValue(i.Arguments[1]);
                var value   = GetArgumentValue(i.Arguments[2]);
                return(asignee + " = " + str + " + " + value + ";");
            }

            case PapyrusOpCodes.Fsub:
            case PapyrusOpCodes.Isub:
            {
                return(DoMath(i, "-"));
            }

            case PapyrusOpCodes.Fadd:
            case PapyrusOpCodes.Iadd:
            {
                return(DoMath(i, "+"));
            }

            case PapyrusOpCodes.Imod:
            {
                return(DoMath(i, "%"));
            }

            case PapyrusOpCodes.Fdiv:
            case PapyrusOpCodes.Idiv:
            {
                return(DoMath(i, "/"));
            }

            case PapyrusOpCodes.Fmul:
            case PapyrusOpCodes.Imul:
            {
                return(DoMath(i, "*"));
            }

            case PapyrusOpCodes.Fneg:
            case PapyrusOpCodes.Ineg:
            {
                var comment = WritePapyrusInstruction(i) + Environment.NewLine;
                var asignee = GetArgumentValue(i.Arguments[0]);
                var target  = GetArgumentValue(i.Arguments[1]);
                return(comment + asignee + " = -" + target + ";");
            }

            case PapyrusOpCodes.CmpEq:
            {
                return(DoMath(i, "=="));
            }

            case PapyrusOpCodes.CmpGt:
            {
                return(DoMath(i, ">"));
            }

            case PapyrusOpCodes.CmpGte:
            {
                return(DoMath(i, ">="));
            }

            case PapyrusOpCodes.CmpLt:
            {
                return(DoMath(i, "<"));
            }

            case PapyrusOpCodes.CmpLte:
            {
                return(DoMath(i, "<="));
            }

            case PapyrusOpCodes.Not:
            {
                // var comment = WritePapyrusInstruction(i) + Environment.NewLine;

                var assignee = i.GetArg(0);
                var target   = i.GetArg(1);
                return(assignee + " = !" + target + ";");
            }

            case PapyrusOpCodes.Jmp:
            {
                var destination = GetArgumentValue(i.Arguments[0]);
                return("// " + i.OpCode + " " + destination + " (offset: " +
                       (i.Offset + int.Parse(destination)) + ")");
            }

            case PapyrusOpCodes.Jmpt:
            case PapyrusOpCodes.Jmpf:
            {
                var boolVal     = GetArgumentValue(i.Arguments[0]);
                var destination = GetArgumentValue(i.Arguments[1]);
                return("// " + i.OpCode + " " + boolVal + " " + destination + " (offset: " +
                       (i.Offset + int.Parse(destination)) + ")");
            }

            default:
            {
                return(WritePapyrusInstruction(i));
            }
            }
            return(null);
        }
예제 #6
0
        /// <summary>
        ///     Writes the method.
        /// </summary>
        /// <param name="method">The method.</param>
        /// <param name="type">The type.</param>
        /// <param name="asm">The asm.</param>
        /// <param name="indent">The indent.</param>
        /// <param name="isGetter">if set to <c>true</c> [is getter].</param>
        /// <param name="isSetter">if set to <c>true</c> [is setter].</param>
        private void WriteMethod(PapyrusMethodDefinition method, PapyrusTypeDefinition type,
                                 PapyrusAssemblyDefinition asm, int indent, PapyrusPropertyDefinition prop = null, bool isGetter = false,
                                 bool isSetter = false)
        {
            // SetGlobalIndent(indent);
            if (!isGetter && !isSetter)
            {
                if (method.Documentation != null && !string.IsNullOrEmpty(method.Documentation.Value))
                {
                    WriteDoc(method.Documentation, indent);
                }
                Append("public " +
                       (method.IsGlobal ? "static " : "") +
                       (method.IsNative ? "extern " : "") +
                       ((string)method.ReturnTypeName).Replace("None", "void") + " " +
                       (string)method.Name
                       , indent);
                Append("(");
                Append(string.Join(",",
                                   method.Parameters.Select(i => (string)i.TypeName + " " + (string)i.Name)));
                AppendLine(")");
            }
            AppendLine("{", indent);
            //if (isGetter)
            //{
            //    if (prop != null)
            //    {
            //        prop.
            //    }
            //    // type.Fields.FirstOrDefault(f=>f.Name.Value.Contains());
            //    AppendLine("return <backing_field>;", indent + 1);
            //}
            //else if (isSetter)
            //{
            //    AppendLine("<backing_field> = value;", indent + 1);
            //}
            //else
            {
                if (method.HasBody)
                {
                    var debug =
                        asm.DebugInfo.MethodDescriptions.FirstOrDefault(
                            m => method.Name != null && m.Name.Value == method.Name.Value);
                    if (debug != null)
                    {
                        AppendLine("// DEBUG LINE NUMBER: " + string.Join(",", debug.BodyLineNumbers.ToArray()),
                                   indent + 1);
                    }
                    foreach (var var in method.GetVariables())
                    {
                        if (var.Name.Value.ToLower() == "::nonevar")
                        {
                            continue;
                        }

                        var typeName = (string)var.TypeName;
                        if (typeName.Contains("#"))
                        {
                            AppendLine("// Struct Variable: " + typeName, indent + 1);
                            AppendLine(typeName.Split('#').LastOrDefault() + " " + (string)var.Name + ";", indent + 1);
                        }
                        else
                        {
                            AppendLine(typeName + " " + (string)var.Name + ";", indent + 1);
                        }
                    }


                    //var flowGraphBuilder = new PapyrusControlFlowGraphBuilder(method);
                    //var graph = flowGraphBuilder.Build();
                    //graph.ComputeDominance();
                    //graph.ComputeDominanceFrontier();
                    //var nodes = graph.Nodes.Skip(2).ToList();
                    //var count = nodes.Count;

                    foreach (var instruction in method.Body.Instructions)
                    {
                        var instructionString = WriteInstruction(instruction, method, type);
                        foreach (
                            var row in instructionString.Split(new[] { Environment.NewLine }, StringSplitOptions.None))
                        {
                            AppendLine("/* " + instruction.Offset + " */ " + row, indent + 1);
                        }
                    }

                    //List<PapyrusInstruction> targetEnd = new List<PapyrusInstruction>();
                    //foreach (var n in nodes)
                    //{

                    //    var end = n.End;

                    //    //if (count > 1)
                    //    //    AppendLine("/* ====== Node Start ====== */", 1);

                    //    foreach (var instruction in n.Instructions)
                    //    {
                    //        Append("/* " + instruction.Offset + " */ ", 1);

                    //        WriteInstruction(indent, instruction, method, type, asm);
                    //    }

                    //    if (end != null && IsJump(end.OpCode))
                    //    {

                    //        var direction = int.Parse(end.GetArg(IsJumpf(end.OpCode) || IsJumpt(end.OpCode) ? 1 : 0));
                    //        if (direction < 0)
                    //        {
                    //            // LOOP?
                    //        }
                    //        else
                    //        {
                    //            // BRANCHING
                    //        }
                    //    }
                    //}
                }
            }
            AppendLine("}", indent);
        }