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