using System; using System.Collections.Generic; using System.Reflection.Emit; using System.Text; using Sunweaver.DataPrototypes; namespace Sunweaver.Commands.Abstracts { /// /// An abstract class that handles the fizzle behavior for binary math operations /// abstract public class BinaryOperation : BasePair { protected VirtualMachine VM = null; public override void Implementation(VirtualMachine VM) { //fizzles if there aren't enough values if (VM.Stack.Count() < 2) return; long b = VM.Stack.Pop(); long a = VM.Stack.Pop(); this.VM = VM; Operation(a, b); } internal override void Compile(ILGenerator il, Locals locals) { var cont = il.DefineLabel(); il.Emit(OpCodes.Ldloc, locals[typeof(VirtualMachine)]); il.Emit(OpCodes.Ldfld, typeof(VirtualMachine).GetField("Stack")); il.Emit(OpCodes.Call, typeof(IntStack).GetMethod("Count")); il.Emit(OpCodes.Ldc_I4_2); il.Emit(OpCodes.Blt_S, cont); // We dont return, just go the end of this method il.Emit(OpCodes.Ldloc, locals[typeof(VirtualMachine)]); il.Emit(OpCodes.Ldfld, typeof(VirtualMachine).GetField("Stack")); il.Emit(OpCodes.Call, typeof(IntStack).GetMethod("Pop")); il.Emit(OpCodes.Conv_I8); il.Emit(OpCodes.Stloc, locals[typeof(long), 1]); il.Emit(OpCodes.Ldloc, locals[typeof(VirtualMachine)]); il.Emit(OpCodes.Ldfld, typeof(VirtualMachine).GetField("Stack")); il.Emit(OpCodes.Call, typeof(IntStack).GetMethod("Pop")); il.Emit(OpCodes.Conv_I8); il.Emit(OpCodes.Stloc, locals[typeof(long), 0]); CompileOperation(il, locals); il.MarkLabel(cont); } /// /// Child members implement this with their specifics /// /// top value on the int stack /// second to top value on the int stack public abstract void Operation(long a, long b); /// /// Abstract interface that child classes implement /// /// /// The long variables for the operation are stored in long0 and long1 of locals. /// public abstract void CompileOperation(ILGenerator il, Locals locals); } }