mirror of
https://github.com/Smaug123/WoofWare.PawPrint
synced 2025-10-05 06:08:39 +00:00
Add some more tests (#128)
This commit is contained in:
255
WoofWare.PawPrint.Test/sourcesPure/ComparisonOperations.cs
Normal file
255
WoofWare.PawPrint.Test/sourcesPure/ComparisonOperations.cs
Normal file
@@ -0,0 +1,255 @@
|
||||
public class TestComparisonOperations
|
||||
{
|
||||
// Test Ceq: Compare equal
|
||||
public static int TestCompareEqual()
|
||||
{
|
||||
// Integer equality
|
||||
if ((5 == 5) != true) return 1;
|
||||
if ((5 == 6) != false) return 2;
|
||||
if ((int.MaxValue == int.MaxValue) != true) return 3;
|
||||
if ((int.MinValue == int.MaxValue) != false) return 4;
|
||||
|
||||
// Negative numbers
|
||||
if ((-1 == -1) != true) return 5;
|
||||
if ((-5 == 5) != false) return 6;
|
||||
|
||||
// Long equality
|
||||
if ((100L == 100L) != true) return 7;
|
||||
if ((100L == 101L) != false) return 8;
|
||||
|
||||
// Mixed sizes (after promotion)
|
||||
int i = 42;
|
||||
long l = 42L;
|
||||
if ((l == (long)i) != true) return 9;
|
||||
|
||||
// Zero comparisons
|
||||
if ((0 == 0) != true) return 10;
|
||||
if ((0 == 1) != false) return 11;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Test Cgt: Compare greater than (signed)
|
||||
public static int TestCompareGreaterThan()
|
||||
{
|
||||
// Positive integers
|
||||
if ((10 > 5) != true) return 20;
|
||||
if ((5 > 10) != false) return 21;
|
||||
if ((5 > 5) != false) return 22;
|
||||
|
||||
// Negative integers
|
||||
if ((-5 > -10) != true) return 23;
|
||||
if ((-10 > -5) != false) return 24;
|
||||
if ((5 > -5) != true) return 25;
|
||||
if ((-5 > 5) != false) return 26;
|
||||
|
||||
// Boundary values
|
||||
if ((int.MaxValue > int.MinValue) != true) return 27;
|
||||
if ((int.MinValue > int.MaxValue) != false) return 28;
|
||||
if ((int.MaxValue > (int.MaxValue - 1)) != true) return 29;
|
||||
|
||||
// Zero comparisons
|
||||
if ((1 > 0) != true) return 30;
|
||||
if ((0 > 1) != false) return 31;
|
||||
if ((-1 > 0) != false) return 32;
|
||||
if ((0 > -1) != true) return 33;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Test Cgt_un: Compare greater than (unsigned)
|
||||
public static int TestCompareGreaterThanUnsigned()
|
||||
{
|
||||
uint a = 10;
|
||||
uint b = 5;
|
||||
|
||||
// Basic unsigned comparison
|
||||
if ((a > b) != true) return 40;
|
||||
if ((b > a) != false) return 41;
|
||||
if ((a > a) != false) return 42;
|
||||
|
||||
// High bit set (would be negative if signed)
|
||||
uint high = 0x80000000;
|
||||
uint low = 0x7FFFFFFF;
|
||||
if ((high > low) != true) return 43; // Unsigned: high > low
|
||||
|
||||
// Maximum values
|
||||
uint max = uint.MaxValue;
|
||||
uint min = uint.MinValue;
|
||||
if ((max > min) != true) return 44;
|
||||
if ((min > max) != false) return 45;
|
||||
|
||||
// Interpret negative as unsigned
|
||||
uint negAsUint = unchecked((uint)-1);
|
||||
uint one = 1;
|
||||
if ((negAsUint > one) != true) return 46; // 0xFFFFFFFF > 1
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Test Clt: Compare less than (signed)
|
||||
public static int TestCompareLessThan()
|
||||
{
|
||||
// Positive integers
|
||||
if ((5 < 10) != true) return 50;
|
||||
if ((10 < 5) != false) return 51;
|
||||
if ((5 < 5) != false) return 52;
|
||||
|
||||
// Negative integers
|
||||
if ((-10 < -5) != true) return 53;
|
||||
if ((-5 < -10) != false) return 54;
|
||||
if ((-5 < 5) != true) return 55;
|
||||
if ((5 < -5) != false) return 56;
|
||||
|
||||
// Boundary values
|
||||
if ((int.MinValue < int.MaxValue) != true) return 57;
|
||||
if ((int.MaxValue < int.MinValue) != false) return 58;
|
||||
|
||||
// Zero comparisons
|
||||
if ((0 < 1) != true) return 59;
|
||||
if ((1 < 0) != false) return 60;
|
||||
if ((0 < -1) != false) return 61;
|
||||
if ((-1 < 0) != true) return 62;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Test Clt_un: Compare less than (unsigned)
|
||||
public static int TestCompareLessThanUnsigned()
|
||||
{
|
||||
uint a = 5;
|
||||
uint b = 10;
|
||||
|
||||
// Basic unsigned comparison
|
||||
if ((a < b) != true) return 70;
|
||||
if ((b < a) != false) return 71;
|
||||
if ((a < a) != false) return 72;
|
||||
|
||||
// High bit set
|
||||
uint high = 0x80000000;
|
||||
uint low = 0x7FFFFFFF;
|
||||
if ((low < high) != true) return 73; // Unsigned: low < high
|
||||
|
||||
// Boundary values
|
||||
uint max = uint.MaxValue;
|
||||
uint min = uint.MinValue;
|
||||
if ((min < max) != true) return 74;
|
||||
if ((max < min) != false) return 75;
|
||||
|
||||
// Negative as unsigned
|
||||
uint one = 1;
|
||||
uint negAsUint = unchecked((uint)-1);
|
||||
if ((one < negAsUint) != true) return 76; // 1 < 0xFFFFFFFF
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Test comparison combinations
|
||||
public static int TestComparisonCombinations()
|
||||
{
|
||||
int x = 10;
|
||||
int y = 20;
|
||||
int z = 10;
|
||||
|
||||
// Equality chains
|
||||
if ((x == z) != true) return 80;
|
||||
if ((x == y) != false) return 81;
|
||||
|
||||
// Inequality combinations
|
||||
if ((x < y && y > x) != true) return 82;
|
||||
if ((x < y && x == y) != false) return 83;
|
||||
|
||||
// Transitive comparisons
|
||||
if (x < y && y < 30)
|
||||
{
|
||||
if ((x < 30) != true) return 84;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 85;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Test comparisons with different types
|
||||
public static int TestMixedTypeComparisons()
|
||||
{
|
||||
// byte comparisons (unsigned by default)
|
||||
byte b1 = 200;
|
||||
byte b2 = 100;
|
||||
if ((b1 > b2) != true) return 90;
|
||||
|
||||
// sbyte comparisons (signed)
|
||||
sbyte sb1 = -50;
|
||||
sbyte sb2 = 50;
|
||||
if ((sb1 < sb2) != true) return 91;
|
||||
|
||||
// short comparisons
|
||||
short s1 = -1000;
|
||||
short s2 = 1000;
|
||||
if ((s1 < s2) != true) return 92;
|
||||
if ((s1 == s2) != false) return 93;
|
||||
|
||||
// long comparisons
|
||||
long l1 = long.MaxValue;
|
||||
long l2 = long.MinValue;
|
||||
if ((l1 > l2) != true) return 94;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Test null comparisons
|
||||
public static int TestNullComparisons()
|
||||
{
|
||||
object obj1 = null;
|
||||
object obj2 = null;
|
||||
object obj3 = new object();
|
||||
|
||||
// Null equality
|
||||
if ((obj1 == obj2) != true) return 100;
|
||||
if ((obj1 == obj3) != false) return 101;
|
||||
if ((obj3 == obj1) != false) return 102;
|
||||
|
||||
// String null comparisons
|
||||
string s1 = null;
|
||||
string s2 = null;
|
||||
string s3 = "";
|
||||
|
||||
if ((s1 == s2) != true) return 103;
|
||||
if ((s1 == s3) != false) return 104;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int Main(string[] argv)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = TestCompareEqual();
|
||||
if (result != 0) return 100 + result;
|
||||
|
||||
result = TestCompareGreaterThan();
|
||||
if (result != 0) return 200 + result;
|
||||
|
||||
result = TestCompareGreaterThanUnsigned();
|
||||
if (result != 0) return 300 + result;
|
||||
|
||||
result = TestCompareLessThan();
|
||||
if (result != 0) return 400 + result;
|
||||
|
||||
result = TestCompareLessThanUnsigned();
|
||||
if (result != 0) return 500 + result;
|
||||
|
||||
result = TestComparisonCombinations();
|
||||
if (result != 0) return 600 + result;
|
||||
|
||||
result = TestMixedTypeComparisons();
|
||||
if (result != 0) return 700 + result;
|
||||
|
||||
result = TestNullComparisons();
|
||||
if (result != 0) return 800 + result;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
184
WoofWare.PawPrint.Test/sourcesPure/StackOperations.cs
Normal file
184
WoofWare.PawPrint.Test/sourcesPure/StackOperations.cs
Normal file
@@ -0,0 +1,184 @@
|
||||
public class TestStackOperations
|
||||
{
|
||||
// Test LdArg0-3: Load method arguments
|
||||
public static int TestLoadArguments(int arg0, int arg1, int arg2, int arg3)
|
||||
{
|
||||
// LdArg0 loads 'this' for instance methods or first arg for static
|
||||
if (arg0 != 10) return 1;
|
||||
|
||||
// LdArg1 loads second argument
|
||||
if (arg1 != 20) return 2;
|
||||
|
||||
// LdArg2 loads third argument
|
||||
if (arg2 != 30) return 3;
|
||||
|
||||
// LdArg3 loads fourth argument
|
||||
if (arg3 != 40) return 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Test Ldloc_0-3 and Stloc_0-3: Load/store local variables
|
||||
public static int TestLocalVariables()
|
||||
{
|
||||
int local0 = 100;
|
||||
int local1 = 200;
|
||||
int local2 = 300;
|
||||
int local3 = 400;
|
||||
|
||||
// Test loading locals
|
||||
if (local0 != 100) return 10;
|
||||
if (local1 != 200) return 11;
|
||||
if (local2 != 300) return 12;
|
||||
if (local3 != 400) return 13;
|
||||
|
||||
// Test storing to locals
|
||||
local0 = local1 + local2; // Stloc_0
|
||||
if (local0 != 500) return 14;
|
||||
|
||||
local1 = local2 * 2; // Stloc_1
|
||||
if (local1 != 600) return 15;
|
||||
|
||||
local2 = local3 - 100; // Stloc_2
|
||||
if (local2 != 300) return 16;
|
||||
|
||||
local3 = local0 / 5; // Stloc_3
|
||||
if (local3 != 100) return 17;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Test Pop: Remove top stack value
|
||||
public static int TestPop()
|
||||
{
|
||||
int value = 42;
|
||||
|
||||
// Push value on stack then pop it
|
||||
PushAndPop(value);
|
||||
|
||||
// If we get here, pop worked
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static void PushAndPop(int value)
|
||||
{
|
||||
// The compiler will generate pop instructions
|
||||
// for unused return values
|
||||
GetValue();
|
||||
GetValue();
|
||||
}
|
||||
|
||||
private static int GetValue()
|
||||
{
|
||||
return 123;
|
||||
}
|
||||
|
||||
// Test Dup: Duplicate top stack value
|
||||
public static int TestDup()
|
||||
{
|
||||
int value = 50;
|
||||
|
||||
// Dup is used when same value is needed twice
|
||||
int result1 = value * value; // Compiler may use dup here
|
||||
if (result1 != 2500) return 20;
|
||||
|
||||
// More complex dup scenario
|
||||
int x = 10;
|
||||
int result2 = AddTwice(x);
|
||||
if (result2 != 20) return 21;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int AddTwice(int val)
|
||||
{
|
||||
// Compiler may generate dup to use val twice
|
||||
return val + val;
|
||||
}
|
||||
|
||||
// Test Ret: Return from method
|
||||
public static int TestReturn()
|
||||
{
|
||||
// Test void return
|
||||
VoidReturn();
|
||||
|
||||
// Test value return
|
||||
int result = ValueReturn(5);
|
||||
if (result != 5) return 30;
|
||||
|
||||
// Test early return
|
||||
result = EarlyReturn(true);
|
||||
if (result != 1) return 31;
|
||||
|
||||
result = EarlyReturn(false);
|
||||
if (result != 2) return 32;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static void VoidReturn()
|
||||
{
|
||||
// Ret with no value
|
||||
return;
|
||||
}
|
||||
|
||||
private static int ValueReturn(int x)
|
||||
{
|
||||
// Ret with value
|
||||
return x;
|
||||
}
|
||||
|
||||
private static int EarlyReturn(bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return 1; // Early ret
|
||||
|
||||
return 2; // Normal ret
|
||||
}
|
||||
|
||||
// Test combinations of stack operations
|
||||
public static int TestStackCombinations()
|
||||
{
|
||||
int a = 10, b = 20, c = 30;
|
||||
|
||||
// Complex expression using multiple locals
|
||||
int result = (a + b) * c - (b - a);
|
||||
if (result != 890) return 40;
|
||||
|
||||
// Nested method calls
|
||||
result = Compute(a, Compute(b, c));
|
||||
if (result != 60) return 41;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int Compute(int x, int y)
|
||||
{
|
||||
return x + y;
|
||||
}
|
||||
|
||||
public static int Main(string[] argv)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = TestLoadArguments(10, 20, 30, 40);
|
||||
if (result != 0) return 100 + result;
|
||||
|
||||
result = TestLocalVariables();
|
||||
if (result != 0) return 200 + result;
|
||||
|
||||
result = TestPop();
|
||||
if (result != 0) return 300 + result;
|
||||
|
||||
result = TestDup();
|
||||
if (result != 0) return 400 + result;
|
||||
|
||||
result = TestReturn();
|
||||
if (result != 0) return 500 + result;
|
||||
|
||||
result = TestStackCombinations();
|
||||
if (result != 0) return 600 + result;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
@@ -69,6 +69,27 @@ module ArithmeticOperation =
|
||||
member _.Name = "add"
|
||||
}
|
||||
|
||||
let addOvf =
|
||||
{ new IArithmeticOperation with
|
||||
member _.Int32Int32 a b = (# "add.ovf" a b : int32 #)
|
||||
member _.Int64Int64 a b = (# "add.ovf" a b : int64 #)
|
||||
member _.FloatFloat a b = (# "add.ovf" a b : float #)
|
||||
member _.NativeIntNativeInt a b = (# "add.ovf" a b : nativeint #)
|
||||
member _.Int32NativeInt a b = (# "add.ovf" a b : nativeint #)
|
||||
member _.NativeIntInt32 a b = (# "add.ovf" a b : nativeint #)
|
||||
|
||||
member _.ManagedPtrManagedPtr _ ptr1 ptr2 =
|
||||
match ptr1, ptr2 with
|
||||
| ManagedPointerSource.Null, _ -> Choice1Of2 ptr2
|
||||
| _, ManagedPointerSource.Null -> Choice1Of2 ptr1
|
||||
| _, _ -> failwith "refusing to add two managed pointers"
|
||||
|
||||
member _.Int32ManagedPtr state val1 ptr2 = addInt32ManagedPtr state val1 ptr2
|
||||
member _.ManagedPtrInt32 state ptr1 val2 = addInt32ManagedPtr state val2 ptr1
|
||||
|
||||
member _.Name = "add.ovf"
|
||||
}
|
||||
|
||||
let sub =
|
||||
{ new IArithmeticOperation with
|
||||
member _.Int32Int32 a b = (# "sub" a b : int32 #)
|
||||
|
@@ -400,7 +400,8 @@ module Intrinsics =
|
||||
let arg1 =
|
||||
match arg1 with
|
||||
| EvalStackValue.ObjectRef h
|
||||
| EvalStackValue.ManagedPointer (ManagedPointerSource.Heap h) -> h
|
||||
| EvalStackValue.ManagedPointer (ManagedPointerSource.Heap h) -> Some h
|
||||
| EvalStackValue.ManagedPointer ManagedPointerSource.Null -> None
|
||||
| EvalStackValue.Int32 _
|
||||
| EvalStackValue.Int64 _
|
||||
| EvalStackValue.Float _ -> failwith $"this isn't a string! {arg1}"
|
||||
@@ -411,32 +412,38 @@ module Intrinsics =
|
||||
let arg2 =
|
||||
match arg2 with
|
||||
| EvalStackValue.ObjectRef h
|
||||
| EvalStackValue.ManagedPointer (ManagedPointerSource.Heap h) -> h
|
||||
| EvalStackValue.ManagedPointer (ManagedPointerSource.Heap h) -> Some h
|
||||
| EvalStackValue.ManagedPointer ManagedPointerSource.Null -> None
|
||||
| EvalStackValue.Int32 _
|
||||
| EvalStackValue.Int64 _
|
||||
| EvalStackValue.Float _ -> failwith $"this isn't a string! {arg2}"
|
||||
| _ -> failwith $"TODO: %O{arg2}"
|
||||
|
||||
if arg1 = arg2 then
|
||||
state
|
||||
|> IlMachineState.pushToEvalStack (CliType.ofBool true) currentThread
|
||||
|> IlMachineState.advanceProgramCounter currentThread
|
||||
|> Some
|
||||
else
|
||||
let areEqual =
|
||||
match arg1, arg2 with
|
||||
| None, None -> true
|
||||
| Some _, None
|
||||
| None, Some _ -> false
|
||||
| Some arg1, Some arg2 ->
|
||||
if arg1 = arg2 then
|
||||
true
|
||||
else
|
||||
|
||||
let arg1 = ManagedHeap.get arg1 state.ManagedHeap
|
||||
let arg2 = ManagedHeap.get arg2 state.ManagedHeap
|
||||
let arg1 = ManagedHeap.get arg1 state.ManagedHeap
|
||||
let arg2 = ManagedHeap.get arg2 state.ManagedHeap
|
||||
|
||||
if
|
||||
AllocatedNonArrayObject.DereferenceField "_firstChar" arg1
|
||||
<> AllocatedNonArrayObject.DereferenceField "_firstChar" arg2
|
||||
then
|
||||
state
|
||||
|> IlMachineState.pushToEvalStack (CliType.ofBool false) currentThread
|
||||
|> IlMachineState.advanceProgramCounter currentThread
|
||||
|> Some
|
||||
else
|
||||
failwith "TODO"
|
||||
if
|
||||
AllocatedNonArrayObject.DereferenceField "_firstChar" arg1
|
||||
<> AllocatedNonArrayObject.DereferenceField "_firstChar" arg2
|
||||
then
|
||||
false
|
||||
else
|
||||
failwith "TODO"
|
||||
|
||||
state
|
||||
|> IlMachineState.pushToEvalStack (CliType.ofBool areEqual) currentThread
|
||||
|> IlMachineState.advanceProgramCounter currentThread
|
||||
|> Some
|
||||
| _ -> None
|
||||
| "System.Private.CoreLib", "Unsafe", "ReadUnaligned" ->
|
||||
let ptr, state = IlMachineState.popEvalStack currentThread state
|
||||
|
@@ -452,7 +452,25 @@ module NullaryIlOp =
|
||||
|> IlMachineState.advanceProgramCounter currentThread
|
||||
|> Tuple.withRight WhatWeDid.Executed
|
||||
|> ExecutionResult.Stepped
|
||||
| Add_ovf -> failwith "TODO: Add_ovf unimplemented"
|
||||
| Add_ovf ->
|
||||
let val2, state = IlMachineState.popEvalStack currentThread state
|
||||
let val1, state = IlMachineState.popEvalStack currentThread state
|
||||
|
||||
let result =
|
||||
try
|
||||
BinaryArithmetic.execute ArithmeticOperation.addOvf state val1 val2 |> Ok
|
||||
with :? OverflowException as e ->
|
||||
Error e
|
||||
|
||||
let state =
|
||||
match result with
|
||||
| Ok result -> state |> IlMachineState.pushToEvalStack' result currentThread
|
||||
| Error excToThrow -> failwith "TODO: throw OverflowException"
|
||||
|
||||
state
|
||||
|> IlMachineState.advanceProgramCounter currentThread
|
||||
|> Tuple.withRight WhatWeDid.Executed
|
||||
|> ExecutionResult.Stepped
|
||||
| Add_ovf_un -> failwith "TODO: Add_ovf_un unimplemented"
|
||||
| Mul ->
|
||||
let val2, state = IlMachineState.popEvalStack currentThread state
|
||||
@@ -617,7 +635,37 @@ module NullaryIlOp =
|
||||
|> IlMachineState.advanceProgramCounter currentThread
|
||||
|
||||
(state, WhatWeDid.Executed) |> ExecutionResult.Stepped
|
||||
| Xor -> failwith "TODO: Xor unimplemented"
|
||||
| Xor ->
|
||||
let v2, state = IlMachineState.popEvalStack currentThread state
|
||||
let v1, state = IlMachineState.popEvalStack currentThread state
|
||||
|
||||
let result =
|
||||
match v1, v2 with
|
||||
| EvalStackValue.Int32 v1, EvalStackValue.Int32 v2 -> v1 ^^^ v2 |> EvalStackValue.Int32
|
||||
| EvalStackValue.Int32 v1, EvalStackValue.NativeInt (NativeIntSource.Verbatim v2) ->
|
||||
int64<int32> v1 ^^^ v2 |> NativeIntSource.Verbatim |> EvalStackValue.NativeInt
|
||||
| EvalStackValue.Int32 _, EvalStackValue.NativeInt _ ->
|
||||
failwith $"can't do binary operation on non-verbatim native int {v2}"
|
||||
| EvalStackValue.Int64 v1, EvalStackValue.Int64 v2 -> v1 ^^^ v2 |> EvalStackValue.Int64
|
||||
| EvalStackValue.NativeInt (NativeIntSource.Verbatim v1), EvalStackValue.Int32 v2 ->
|
||||
v1 ^^^ int64<int32> v2 |> NativeIntSource.Verbatim |> EvalStackValue.NativeInt
|
||||
| EvalStackValue.NativeInt _, EvalStackValue.Int32 _ ->
|
||||
failwith $"can't do binary operation on non-verbatim native int {v1}"
|
||||
| EvalStackValue.NativeInt (NativeIntSource.Verbatim v1),
|
||||
EvalStackValue.NativeInt (NativeIntSource.Verbatim v2) ->
|
||||
v1 ^^^ v2 |> NativeIntSource.Verbatim |> EvalStackValue.NativeInt
|
||||
| EvalStackValue.NativeInt (NativeIntSource.Verbatim _), EvalStackValue.NativeInt _ ->
|
||||
failwith $"can't do binary operation on non-verbatim native int {v2}"
|
||||
| EvalStackValue.NativeInt _, EvalStackValue.NativeInt (NativeIntSource.Verbatim _) ->
|
||||
failwith $"can't do binary operation on non-verbatim native int {v1}"
|
||||
| _, _ -> failwith $"refusing to do binary operation on {v1} and {v2}"
|
||||
|
||||
let state =
|
||||
state
|
||||
|> IlMachineState.pushToEvalStack' result currentThread
|
||||
|> IlMachineState.advanceProgramCounter currentThread
|
||||
|
||||
(state, WhatWeDid.Executed) |> ExecutionResult.Stepped
|
||||
| Conv_I ->
|
||||
let popped, state = IlMachineState.popEvalStack currentThread state
|
||||
let converted = EvalStackValue.toNativeInt popped
|
||||
@@ -935,7 +983,22 @@ module NullaryIlOp =
|
||||
| Conv_ovf_i -> failwith "TODO: Conv_ovf_i unimplemented"
|
||||
| Conv_ovf_u -> failwith "TODO: Conv_ovf_u unimplemented"
|
||||
| Neg -> failwith "TODO: Neg unimplemented"
|
||||
| Not -> failwith "TODO: Not unimplemented"
|
||||
| Not ->
|
||||
let val1, state = IlMachineState.popEvalStack currentThread state
|
||||
|
||||
let result =
|
||||
match val1 with
|
||||
| EvalStackValue.Int32 i -> ~~~i |> EvalStackValue.Int32
|
||||
| EvalStackValue.Int64 i -> ~~~i |> EvalStackValue.Int64
|
||||
| EvalStackValue.ManagedPointer _
|
||||
| EvalStackValue.ObjectRef _ -> failwith "refusing to negate a pointer"
|
||||
| _ -> failwith "TODO"
|
||||
|
||||
state
|
||||
|> IlMachineState.pushToEvalStack' result currentThread
|
||||
|> IlMachineState.advanceProgramCounter currentThread
|
||||
|> Tuple.withRight WhatWeDid.Executed
|
||||
|> ExecutionResult.Stepped
|
||||
| Ldind_ref ->
|
||||
let addr, state = IlMachineState.popEvalStack currentThread state
|
||||
|
||||
|
Reference in New Issue
Block a user