/// <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; } }
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; //} }
//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); }
/// <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); }