/// <summary> /// Parses the instruction. /// </summary> /// <param name="mainProcessor">The main processor.</param> /// <param name="asmCollection">The papyrus assembly collection.</param> /// <param name="instruction">The instruction.</param> /// <param name="targetMethod">The target method.</param> /// <param name="type">The type.</param> /// <returns></returns> public IEnumerable <PapyrusInstruction> Process( IClrInstructionProcessor mainProcessor, IReadOnlyCollection <PapyrusAssemblyDefinition> asmCollection, Instruction instruction, MethodDefinition targetMethod, TypeDefinition type) { var allVariables = mainProcessor.PapyrusMethod.GetVariables(); if (InstructionHelper.IsStoreElement(instruction.OpCode.Code)) { var popCount = Utility.GetStackPopCount(instruction.OpCode.StackBehaviourPop); if (mainProcessor.EvaluationStack.Count >= popCount) { var newValue = mainProcessor.EvaluationStack.Pop(); var itemIndex = mainProcessor.EvaluationStack.Pop(); var itemArray = mainProcessor.EvaluationStack.Pop(); object targetItemIndex = null; object targetItemArray = null; object targetItemValue = null; if (itemIndex.Value is PapyrusVariableReference) { targetItemIndex = itemIndex.Value as PapyrusVariableReference; } else if (itemIndex.Value != null) { targetItemIndex = itemIndex.Value; } if (mainProcessor.PapyrusAssembly.VersionTarget == PapyrusVersionTargets.Skyrim) { if ((targetItemIndex as int?) > 128) { targetItemIndex = 128; } } if (itemArray.Value is PapyrusVariableReference) { targetItemArray = itemArray.Value as PapyrusVariableReference; } if (newValue.Value is PapyrusVariableReference) { targetItemValue = newValue.Value as PapyrusVariableReference; } else if (newValue.Value != null) { targetItemValue = newValue.Value; } return (ArrayUtility.ArrayOf( mainProcessor.CreatePapyrusInstruction(PapyrusOpCodes.ArraySetElement, targetItemArray, targetItemIndex, targetItemValue))); //return "ArraySetElement " + tar + " " + oidx + " " + val; } } if (InstructionHelper.IsStoreLocalVariable(instruction.OpCode.Code) || InstructionHelper.IsStoreFieldObject(instruction.OpCode.Code)) { if (instruction.Operand is FieldReference) { var fref = instruction.Operand as FieldReference; // if the EvaluationStack.Count == 0 // The previous instruction might have been a call that returned a value // Something we did not store... if (mainProcessor.EvaluationStack.Count == 0 && InstructionHelper.IsCallMethod(instruction.Previous.OpCode.Code)) { // If previous was a call, then we should have the evaluation stack with at least one item. // But it seem like we don't... Inject tempvar? } if (mainProcessor.EvaluationStack.Count > 0) { var obj = mainProcessor.EvaluationStack.Pop(); var definedField = mainProcessor.PapyrusType.Fields.FirstOrDefault( f => f.Name.Value == "::" + fref.Name.Replace('<', '_').Replace('>', '_')); if (definedField == null) { definedField = mainProcessor.GetDelegateField(fref); } if (mainProcessor.EvaluationStack.Count > 0) { var nextObj = mainProcessor.EvaluationStack.Peek(); if (nextObj != null && nextObj.TypeName != null && nextObj.TypeName.Contains("#")) { // Store into Struct field. definedField = nextObj.Value as PapyrusFieldDefinition; var structPropName = fref.Name; mainProcessor.EvaluationStack.Pop(); // Just pop it so it does not interfere with any other instructions return (ArrayUtility.ArrayOf( mainProcessor.CreatePapyrusInstruction(PapyrusOpCodes.StructSet, definedField, // location mainProcessor.CreateVariableReferenceFromName(structPropName), // Struct Property/Field Name obj.Value // value ))); } } if (definedField != null) { var structRef = obj.Value as PapyrusStructFieldReference; if (structRef != null) { // StructGet -> TempVar // Var <- TempVar var structSource = structRef.StructSource as PapyrusFieldDefinition; var structField = structRef.StructVariable; var fieldType = GetStructFieldType(asmCollection, structSource, structField); // 1. Create Temp Var bool isStructAccess; var tempVar = mainProcessor.GetTargetVariable(instruction, null, out isStructAccess, fieldType, true); // 2. StructGet -> tempVar // 3. Assign var <- tempVar return(ArrayUtility.ArrayOf( mainProcessor.CreatePapyrusInstruction(PapyrusOpCodes.StructGet, mainProcessor.CreateVariableReferenceFromName(tempVar), structSource, structField), mainProcessor.CreatePapyrusInstruction(PapyrusOpCodes.Assign, definedField, mainProcessor.CreateVariableReferenceFromName(tempVar)))); } if (obj.Value is PapyrusParameterDefinition) { var varRef = obj.Value as PapyrusParameterDefinition; // definedField.FieldVariable = varRef.; // CreatePapyrusInstruction(PapyrusOpCode.Assign, definedField.Name.Value, varRef.Name.Value) return (ArrayUtility.ArrayOf( mainProcessor.CreatePapyrusInstruction(PapyrusOpCodes.Assign, definedField, varRef))); } if (obj.Value is PapyrusVariableReference) { var varRef = obj.Value as PapyrusVariableReference; // definedField.Value = varRef.Value; definedField.DefaultValue = varRef; definedField.DefaultValue.Type = PapyrusPrimitiveType.Reference; // CreatePapyrusInstruction(PapyrusOpCode.Assign, definedField.Name.Value, varRef.Name.Value) if (varRef.IsDelegateReference) { return(new PapyrusInstruction[0]); } return (ArrayUtility.ArrayOf( mainProcessor.CreatePapyrusInstruction(PapyrusOpCodes.Assign, definedField, varRef))); } //definedField.FieldVariable.Value = // Utility.TypeValueConvert(definedField.FieldVariable.TypeName.Value, obj.Value); var targetValue = valueTypeConverter.Convert(definedField.DefaultValue.TypeName.Value, obj.Value); return (ArrayUtility.ArrayOf( mainProcessor.CreatePapyrusInstruction(PapyrusOpCodes.Assign, definedField, targetValue))); // definedField.FieldVariable.Value // "Assign " + definedField.Name + " " + definedField.Value; } } } var index = (int)mainProcessor.GetNumericValue(instruction); object outVal = null; if (index < allVariables.Count) { if (mainProcessor.EvaluationStack.Count > 0) { var heapObj = mainProcessor.EvaluationStack.Pop(); var structRef = heapObj.Value as PapyrusStructFieldReference; if (structRef != null) { // Grabbing value from struct var structSource = structRef.StructSource as PapyrusFieldDefinition; var structField = structRef.StructVariable; var fieldType = GetStructFieldType(asmCollection, structSource, structField); // 1. Create Temp Var bool isStructAccess; var tempVar = mainProcessor.GetTargetVariable(instruction, null, out isStructAccess, fieldType, true); // 2. StructGet -> tempVar // 3. Assign var <- tempVar return(ArrayUtility.ArrayOf( mainProcessor.CreatePapyrusInstruction(PapyrusOpCodes.StructGet, mainProcessor.CreateVariableReferenceFromName(tempVar), structSource, structField), mainProcessor.CreatePapyrusInstruction(PapyrusOpCodes.Assign, allVariables[index], mainProcessor.CreateVariableReferenceFromName(tempVar)))); } if (heapObj.Value is PapyrusFieldDefinition) { heapObj.Value = (heapObj.Value as PapyrusFieldDefinition).DefaultValue; } if (heapObj.Value is PapyrusVariableReference) { var varRef = heapObj.Value as PapyrusVariableReference; allVariables[index].Value = allVariables[index].Name.Value; //varRef.Name.Value; // "Assign " + allVariables[(int)index].Name.Value + " " + varRef.Name.Value; return (ArrayUtility.ArrayOf( mainProcessor.CreatePapyrusInstruction(PapyrusOpCodes.Assign, allVariables[index], varRef))); } // allVariables[index].Value outVal = valueTypeConverter.Convert(allVariables[index].TypeName.Value, heapObj.Value); } var valout = outVal; //allVariables[index].Value; //if (valout is string) //{ // stringValue = valout.ToString(); //} if (valout is PapyrusFieldDefinition) { return (ArrayUtility.ArrayOf(mainProcessor.CreatePapyrusInstruction( PapyrusOpCodes.Assign, allVariables[index], valout as PapyrusFieldDefinition))); } if (valout is PapyrusVariableReference) { return (ArrayUtility.ArrayOf(mainProcessor.CreatePapyrusInstruction( PapyrusOpCodes.Assign, allVariables[index], valout as PapyrusVariableReference))); } if (valout is PapyrusParameterDefinition) { return (ArrayUtility.ArrayOf(mainProcessor.CreatePapyrusInstruction( PapyrusOpCodes.Assign, allVariables[index], valout as PapyrusParameterDefinition))); } // "Assign " + allVariables[(int)index].Name.Value + " " + valoutStr; if (valout == null) { valout = "None"; } if (allVariables[index].IsDelegateReference) { // If this is a delegate reference, then we do not want to assign this value to anything. return(new PapyrusInstruction[0]); } return (ArrayUtility.ArrayOf(mainProcessor.CreatePapyrusInstruction(PapyrusOpCodes.Assign, allVariables[index], valout))); } } return(new PapyrusInstruction[0]); }