public void UnaryExpression(CParser.UnaryExpression UnaryExpression)
{
var Operator = UnaryExpression.Operator;
var OperatorPosition = UnaryExpression.OperatorPosition;
var Right = UnaryExpression.Right;
var RightCType = Right.GetCachedCType(this);
var RightType = ConvertCTypeToType(RightCType);
switch (Operator)
{
case "~":
{
if (OperatorPosition != CParser.OperatorPosition.Left) throw (new InvalidOperationException());
DoGenerateAddress(false, () => { Traverse(Right); });
SafeILGenerator.UnaryOperation(SafeUnaryOperator.Not);
}
break;
case "!":
{
if (OperatorPosition != CParser.OperatorPosition.Left) throw (new InvalidOperationException());
DoGenerateAddress(false, () => { Traverse(Right); });
SafeILGenerator.ConvertTo<bool>();
SafeILGenerator.Push(0);
SafeILGenerator.CompareBinary(SafeBinaryComparison.Equals);
}
break;
case "-":
{
if (OperatorPosition != CParser.OperatorPosition.Left) throw (new InvalidOperationException());
DoGenerateAddress(false, () => { Traverse(Right); });
SafeILGenerator.UnaryOperation(SafeUnaryOperator.Negate);
}
break;
case "+":
{
if (OperatorPosition != CParser.OperatorPosition.Left) throw (new InvalidOperationException());
DoGenerateAddress(false, () => { Traverse(Right); });
}
break;
case "++":
case "--":
{
/*
var RightFieldAccess = Right as CParser.FieldAccessExpression;
if (RightFieldAccess != null)
{
}
*/
//DoGenerateAddress(true, () => { Traverse(Right); });
LocalBuilder VariableToIncrementAddressLocal = null;
LocalBuilder InitialVariableToIncrementValueLocal = null;
LocalBuilder PostVariableToIncrementValueLocal = null;
//RequireYieldResult = true;
if (RequireYieldResult)
{
VariableToIncrementAddressLocal = SafeILGenerator.DeclareLocal(typeof(IntPtr));
}
// Load address.
DoGenerateAddress(true, () => { Traverse(Right); });
//Console.WriteLine("DEBUG: {0}", RightType);
// Store.
if (VariableToIncrementAddressLocal != null)
{
// Store initial address
SafeILGenerator.Duplicate();
SafeILGenerator.StoreLocal(VariableToIncrementAddressLocal);
}
// Load Value
SafeILGenerator.Duplicate();
SafeILGenerator.LoadIndirect(RightType);
if (RequireYieldResult && (OperatorPosition == CParser.OperatorPosition.Right))
{
// Store initial value
InitialVariableToIncrementValueLocal = SafeILGenerator.DeclareLocal(RightType);
SafeILGenerator.Duplicate();
SafeILGenerator.StoreLocal(InitialVariableToIncrementValueLocal);
}
// Increment/Decrement by 1 the value.
if (RightType.IsPointer)
{
SafeILGenerator.Sizeof(RightType.GetElementType());
}
else
{
SafeILGenerator.Push(1);
}
SafeILGenerator.BinaryOperation((Operator == "++") ? SafeBinaryOperator.AdditionSigned : SafeBinaryOperator.SubstractionSigned);
if (RequireYieldResult && (OperatorPosition == CParser.OperatorPosition.Left))
{
// Store the post value
PostVariableToIncrementValueLocal = SafeILGenerator.DeclareLocal(RightType);
SafeILGenerator.Duplicate();
SafeILGenerator.StoreLocal(PostVariableToIncrementValueLocal);
}
// Store the updated value.
SafeILGenerator.StoreIndirect(RightType);
/*
if (GenerateAddress)
{
//throw(new NotImplementedException("Can't generate address for a ++ or -- expression"));
SafeILGenerator.LoadLocal(VariableToIncrementAddressLocal);
}
else
*/
if (RequireYieldResult)
{
if (OperatorPosition == CParser.OperatorPosition.Left)
{
SafeILGenerator.LoadLocal(PostVariableToIncrementValueLocal);
}
else if (OperatorPosition == CParser.OperatorPosition.Right)
{
SafeILGenerator.LoadLocal(InitialVariableToIncrementValueLocal);
}
}
}
break;
default:
throw (new NotImplementedException(String.Format("Unimplemented unary operator '{0}'", Operator)));
}
}