/// <summary> /// Convert StackValue to boolean typed StackValue. Returns /// StackValue.Null if not able to do conversion. /// </summary> /// <param name="core"></param> /// <returns></returns> public StackValue ToBoolean(Core core) { switch (optype) { case AddressType.Boolean: return(this); case AddressType.Int: return(BuildBoolean(opdata != 0)); case AddressType.Null: return(StackValue.Null); case AddressType.Double: bool b = !Double.IsNaN(RawDoubleValue) && !RawDoubleValue.Equals(0.0); return(BuildBoolean(b)); case AddressType.Pointer: return(StackValue.BuildBoolean(true)); case AddressType.String: string str = core.Heap.GetString(this); return(string.IsNullOrEmpty(str) ? StackValue.False : StackValue.True); case AddressType.Char: char c = EncodingUtils.ConvertInt64ToCharacter(opdata); return((c == 0) ? StackValue.False : StackValue.True); default: return(StackValue.Null); } }
/// <summary> /// Convert StackValue to boolean typed StackValue. Returns /// StackValue.Null if not able to do conversion. /// </summary> /// <param name="core"></param> /// <returns></returns> public StackValue ToBoolean(Core core) { switch (optype) { case AddressType.Boolean: return(this); case AddressType.Int: return(BuildBoolean(opdata != 0)); case AddressType.Null: return(StackValue.Null); case AddressType.Double: bool b = !Double.IsNaN(RawDoubleValue) && !RawDoubleValue.Equals(0.0); return(BuildBoolean(b)); case AddressType.Pointer: return(StackValue.BuildBoolean(true)); case AddressType.String: int size = ArrayUtils.GetElementSize(this, core); return((size == 0) ? StackValue.False : StackValue.True); case AddressType.Char: char c = EncodingUtils.ConvertInt64ToCharacter(opdata); return((c == 0) ? StackValue.False : StackValue.True); default: return(StackValue.Null); } }
public static StackValue AsBoolean(this StackValue operand, Core core) { switch (operand.optype) { case AddressType.Boolean: case AddressType.Int: return(BuildBoolean(operand.opdata != 0)); case AddressType.Null: return(BuildNull()); //BuildBoolean(false); case AddressType.Double: bool b = !(Double.IsNaN(operand.opdata_d) || operand.opdata_d.Equals(0.0)); return(BuildBoolean(b)); case AddressType.Pointer: return(BuildBoolean(true)); case AddressType.String: if (ArrayUtils.GetElementSize(operand, core) == 0) { return(BuildBoolean(false)); } return(BuildBoolean(true)); case AddressType.Char: if (EncodingUtils.ConvertInt64ToCharacter(operand.opdata) == 0) { return(BuildBoolean(false)); } return(BuildBoolean(true)); default: return(BuildNull()); } }
public static StackValue Coerce(StackValue sv, Type targetType, Core core) { //@TODO(Jun): FIX ME - abort coersion for default args if (sv.IsDefaultArgument) { return(sv); } if (!( sv.metaData.type == targetType.UID || (core.ClassTable.ClassNodes[sv.metaData.type].ConvertibleTo(targetType.UID)) || sv.IsArray)) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kConversionNotPossible, ProtoCore.StringConstants.kConvertNonConvertibleTypes); return(StackValue.Null); } //if it's an array if (sv.IsArray && !targetType.IsIndexable) { //This is an array rank reduction //this may only be performed in recursion and is illegal here string errorMessage = String.Format(ProtoCore.StringConstants.kConvertArrayToNonArray, core.TypeSystem.GetType(targetType.UID)); core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kConversionNotPossible, errorMessage); return(StackValue.Null); } if (sv.IsArray && targetType.IsIndexable) { Validity.Assert(sv.IsArray); //We're being asked to convert an array into an array //walk over the structure converting each othe elements var hpe = core.Heap.GetHeapElement(sv); #if GC_REFERENCE_COUNTING var isTemporary = hpe.Active && hpe.Refcount == 0; #else var isTemporary = false; #endif if (targetType.UID == (int)PrimitiveType.kTypeVar && targetType.rank == DSASM.Constants.kArbitraryRank && isTemporary) { return(sv); } //Validity.Assert(targetType.rank != -1, "Arbitrary rank array conversion not yet implemented {2EAF557F-62DE-48F0-9BFA-F750BBCDF2CB}"); //Decrease level of reductions by one Type newTargetType = new Type(); newTargetType.UID = targetType.UID; if (targetType.rank != Constants.kArbitraryRank) { newTargetType.rank = targetType.rank - 1; } else { if (ArrayUtils.GetMaxRankForArray(sv, core) == 1) { //Last unpacking newTargetType.rank = 0; } else { newTargetType.rank = Constants.kArbitraryRank; } } return(ArrayUtils.CopyArray(sv, newTargetType, core)); } if (!sv.IsArray && !sv.IsNull && targetType.IsIndexable && targetType.rank != DSASM.Constants.kArbitraryRank) { //We're being asked to promote the value into an array if (targetType.rank == 1) { Type newTargetType = new Type(); newTargetType.UID = targetType.UID; newTargetType.Name = targetType.Name; newTargetType.rank = 0; //Upcast once StackValue coercedValue = Coerce(sv, newTargetType, core); GCUtils.GCRetain(coercedValue, core); StackValue newSv = core.Heap.AllocateArray(new StackValue[] { coercedValue }, null); return(newSv); } else { Validity.Assert(targetType.rank > 1, "Target rank should be greater than one for this clause"); Type newTargetType = new Type(); newTargetType.UID = targetType.UID; newTargetType.Name = targetType.Name; newTargetType.rank = targetType.rank - 1; //Upcast once StackValue coercedValue = Coerce(sv, newTargetType, core); GCUtils.GCRetain(coercedValue, core); StackValue newSv = core.Heap.AllocateArray(new StackValue[] { coercedValue }, null); return(newSv); } } if (sv.IsPointer) { StackValue ret = ClassCoerece(sv, targetType, core); return(ret); } //If it's anything other than array, just create a new copy switch (targetType.UID) { case (int)PrimitiveType.kInvalidType: Validity.Assert(false, "Can't convert invalid type"); break; case (int)PrimitiveType.kTypeBool: return(sv.ToBoolean(core)); case (int)PrimitiveType.kTypeChar: { StackValue newSV = sv.ShallowClone(); newSV.metaData = new MetaData { type = (int)PrimitiveType.kTypeChar }; return(newSV); } case (int)PrimitiveType.kTypeDouble: return(sv.ToDouble()); case (int)PrimitiveType.kTypeFunctionPointer: if (sv.metaData.type != (int)PrimitiveType.kTypeFunctionPointer) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeMismatch, ProtoCore.StringConstants.kFailToConverToFunction); return(StackValue.Null); } return(sv); case (int)PrimitiveType.kTypeHostEntityID: { StackValue newSV = sv.ShallowClone(); newSV.metaData = new MetaData { type = (int)PrimitiveType.kTypeHostEntityID }; return(newSV); } case (int)PrimitiveType.kTypeInt: { if (sv.metaData.type == (int)PrimitiveType.kTypeDouble) { //TODO(lukechurch): Once the API is improved (MAGN-5174) //Replace this with a log entry notification //core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeConvertionCauseInfoLoss, ProtoCore.StringConstants.kConvertDoubleToInt); } return(sv.ToInteger()); } case (int)PrimitiveType.kTypeNull: { if (sv.metaData.type != (int)PrimitiveType.kTypeNull) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeMismatch, ProtoCore.StringConstants.kFailToConverToNull); return(StackValue.Null); } return(sv); } case (int)PrimitiveType.kTypePointer: { if (sv.metaData.type != (int)PrimitiveType.kTypeNull) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeMismatch, ProtoCore.StringConstants.kFailToConverToPointer); return(StackValue.Null); } return(sv); } case (int)PrimitiveType.kTypeString: { StackValue newSV = sv.ShallowClone(); newSV.metaData = new MetaData { type = (int)PrimitiveType.kTypeString }; if (sv.metaData.type == (int)PrimitiveType.kTypeChar) { char ch = EncodingUtils.ConvertInt64ToCharacter(newSV.opdata); newSV = StackValue.BuildString(ch.ToString(), core.Heap); } return(newSV); } case (int)PrimitiveType.kTypeVar: { return(sv); } case (int)PrimitiveType.kTypeArray: { return(ArrayUtils.CopyArray(sv, targetType, core)); } default: if (sv.IsNull) { return(StackValue.Null); } else { throw new NotImplementedException("Requested coercion not implemented"); } } throw new NotImplementedException("Requested coercion not implemented"); }
// Verify for single object private static void VerifyInternal(object expectedObject, Obj dsObject, string dsVariable, List <int> indices) { if (expectedObject == null) { if (!dsObject.DsasmValue.IsNull) { Assert.Fail(String.Format("\t{0}{1} is expected to be null, but it isn't.\n{2}", dsVariable, TestFrameWork.BuildIndicesString(indices), TestFrameWork.mErrorMessage)); } return; } Type expectedType = expectedObject.GetType(); if (dsObject.DsasmValue.IsNull && expectedObject != null) { Assert.Fail(String.Format("\tThe value of {0} was null, but wasn't expected to be.\n{1}", dsVariable, mErrorMessage)); } else if (expectedObject is Int32 || expectedObject is Int64) { Int64 expectedValue = Convert.ToInt64(expectedObject); if (dsObject.Type.UID != (int)ProtoCore.PrimitiveType.kTypeInt) { Assert.Fail(String.Format("\t{0}{1} is expected to be {2}, but its actual value is not an integer. \n{2}", dsVariable, BuildIndicesString(indices), expectedValue, mErrorMessage)); } else { TestFrameWork.VerifyPodType(expectedValue, dsObject, dsVariable, indices); } } else if (expectedObject is Double) { Double expectedValue = Convert.ToDouble(expectedObject); if (dsObject.Type.UID != (int)ProtoCore.PrimitiveType.kTypeDouble) { Assert.Fail(String.Format("\t{0}{1} is expected to be {2}, but its actual value is not a double. \n{3}", dsVariable, BuildIndicesString(indices), expectedValue, mErrorMessage)); } else { try { Double dsValue = Convert.ToDouble(dsObject.Payload); if (!MathUtils.Equals(expectedValue, dsValue)) { Assert.Fail(String.Format("\t{0}{1} is expected to be {2}, but its actual value is {3}. \n{4}", dsVariable, BuildIndicesString(indices), expectedValue, dsValue, mErrorMessage)); } } catch (System.InvalidCastException) { Assert.Fail(String.Format("\t{0}{1} is expected to be {2}, but its actual value can't be converted to Double. \n{3}", dsVariable, BuildIndicesString(indices), expectedValue, mErrorMessage)); } } } else if (expectedObject is Boolean) { Boolean expectedValue = Convert.ToBoolean(expectedObject); if (dsObject.Type.UID != (int)ProtoCore.PrimitiveType.kTypeBool) { Assert.Fail(String.Format("\t{0}{1} is expected to be {2}, but its actual type is not bool. \n{3}", dsVariable, BuildIndicesString(indices), expectedValue, mErrorMessage)); } else { TestFrameWork.VerifyPodType(expectedValue, dsObject, dsVariable, indices); } } else if (expectedObject is Char) { Char expectedValue = Convert.ToChar(expectedObject); if (dsObject.Type.UID != (int)ProtoCore.PrimitiveType.kTypeChar) { Assert.Fail(String.Format("\t{0}{1} is expected to be {2}, but its actual type is not char. \n{3}", dsVariable, BuildIndicesString(indices), expectedValue, mErrorMessage)); } else { try { Int64 utf8Encoding = Convert.ToInt64(dsObject.Payload); Char dsValue = EncodingUtils.ConvertInt64ToCharacter(utf8Encoding); if (!expectedObject.Equals(dsValue)) { Assert.Fail(String.Format("\t{0}{1} is expected to be {2}, but its actual value is {3}. \n{4}", dsVariable, BuildIndicesString(indices), expectedValue, dsValue, mErrorMessage)); } } catch (System.InvalidCastException) { Assert.Fail(String.Format("\t{0}{1} is expected to be {2}, but its actual value can't be converted to Char. \n{3}", dsVariable, BuildIndicesString(indices), expectedValue, mErrorMessage)); } } } else if (expectedObject is String) { string stringValue = dsObject.Payload as string; if (stringValue == null) { Assert.Fail(String.Format("\t{0}{1} is expected to be a string, but its actual value is not a string\n{2}", dsVariable, BuildIndicesString(indices), mErrorMessage)); } else if (!expectedObject.Equals(stringValue)) { Assert.Fail(String.Format("\t{0}{1} is expected to be a string \"{2}\", but its actual value is \"{3}\".\n{4}", dsVariable, BuildIndicesString(indices), expectedObject, stringValue, mErrorMessage)); } } else if (typeof(IEnumerable).IsAssignableFrom(expectedType)) { IEnumerable collection = expectedObject as IEnumerable; int index = 0; ProtoCore.DSASM.Mirror.DsasmArray dsArray = dsObject.Payload as ProtoCore.DSASM.Mirror.DsasmArray; if (dsArray == null) { Assert.Fail(String.Format("{0}{1} is expected to be an array, but its actual value isn't an array.\n{2}", dsVariable, BuildIndicesString(indices), mErrorMessage)); } foreach (var item in collection) { indices.Add(index); VerifyInternal(item, dsArray.members[index], dsVariable, indices); indices.RemoveAt(indices.Count - 1); ++index; } } else { Assert.Fail(string.Format("\tUnexpected object type.\n{0}", mErrorMessage)); } }
// Verify for single object private static void VerifyInternal(object expectedObject, Obj dsObject, string dsVariable, List <int> indices) { if (expectedObject == null) { if (dsObject.DsasmValue.optype != ProtoCore.DSASM.AddressType.Null) { Assert.Fail(String.Format("\t{0}{1} is expected to be null, but it isn't.\n{2}", dsVariable, TestFrameWork.BuildIndicesString(indices), TestFrameWork.mErrorMessage)); } } else if (dsObject.DsasmValue.optype == ProtoCore.DSASM.AddressType.Null && expectedObject != null) { Assert.Fail(String.Format("\tThe value of {0} was null, but wasn't expected to be.\n{1}", dsVariable, mErrorMessage)); } else if (expectedObject is Int32 || expectedObject is Int64) { Int64 expectedValue = Convert.ToInt64(expectedObject); if (dsObject.Type.UID != (int)ProtoCore.PrimitiveType.kTypeInt) { Assert.Fail(String.Format("\t{0}{1} is expected to be {2}, but its actual value is not an integer. \n{2}", dsVariable, BuildIndicesString(indices), expectedValue, mErrorMessage)); } else { TestFrameWork.VerifyPodType(expectedValue, dsObject, dsVariable, indices); } } else if (expectedObject is Double) { Double expectedValue = Convert.ToDouble(expectedObject); if (dsObject.Type.UID != (int)ProtoCore.PrimitiveType.kTypeDouble) { Assert.Fail(String.Format("\t{0}{1} is expected to be {2}, but its actual value is not a double. \n{3}", dsVariable, BuildIndicesString(indices), expectedValue, mErrorMessage)); } else { try { Double dsValue = Convert.ToDouble(dsObject.Payload); if (!MathUtils.Equals(expectedValue, dsValue)) { Assert.Fail(String.Format("\t{0}{1} is expected to be {2}, but its actual value is {3}. \n{4}", dsVariable, BuildIndicesString(indices), expectedValue, dsValue, mErrorMessage)); } } catch (System.InvalidCastException) { Assert.Fail(String.Format("\t{0}{1} is expected to be {2}, but its actual value can't be converted to Double. \n{3}", dsVariable, BuildIndicesString(indices), expectedValue, mErrorMessage)); } } } else if (expectedObject is Boolean) { Boolean expectedValue = Convert.ToBoolean(expectedObject); if (dsObject.Type.UID != (int)ProtoCore.PrimitiveType.kTypeBool) { Assert.Fail(String.Format("\t{0}{1} is expected to be {2}, but its actual type is not bool. \n{3}", dsVariable, BuildIndicesString(indices), expectedValue, mErrorMessage)); } else { TestFrameWork.VerifyPodType(expectedValue, dsObject, dsVariable, indices); } } else if (expectedObject is Char) { Char expectedValue = Convert.ToChar(expectedObject); if (dsObject.Type.UID != (int)ProtoCore.PrimitiveType.kTypeChar) { Assert.Fail(String.Format("\t{0}{1} is expected to be {2}, but its actual type is not char. \n{3}", dsVariable, BuildIndicesString(indices), expectedValue, mErrorMessage)); } else { try { Int64 utf8Encoding = Convert.ToInt64(dsObject.Payload); Char dsValue = EncodingUtils.ConvertInt64ToCharacter(utf8Encoding); if (!expectedObject.Equals(dsValue)) { Assert.Fail(String.Format("\t{0}{1} is expected to be {2}, but its actual value is {3}. \n{4}", dsVariable, BuildIndicesString(indices), expectedValue, dsValue, mErrorMessage)); } } catch (System.InvalidCastException) { Assert.Fail(String.Format("\t{0}{1} is expected to be {2}, but its actual value can't be converted to Char. \n{3}", dsVariable, BuildIndicesString(indices), expectedValue, mErrorMessage)); } } } else if (expectedObject is String) { char[] chars = (expectedObject as String).ToCharArray(); object[] objs = new object[chars.Length]; Array.Copy(chars, objs, chars.Length); ProtoCore.DSASM.Mirror.DsasmArray dsArray = dsObject.Payload as ProtoCore.DSASM.Mirror.DsasmArray; if (dsArray == null) { Assert.Fail(String.Format("\t{0}{1} is expected to be a string, but its actual value is not a string\n{2}", dsVariable, BuildIndicesString(indices), mErrorMessage)); } else if (chars.Count() != dsArray.members.Count()) { Assert.Fail(String.Format("\t{0}{1} is expected to be a string of length {2}, but its actual length is {3}.\n{4}", dsVariable, BuildIndicesString(indices), objs.Count(), dsArray.members.Count(), mErrorMessage)); } else { for (int i = 0; i < objs.Count(); ++i) { indices.Add(i); TestFrameWork.VerifyInternal(objs[i], dsArray.members[i], dsVariable, indices); indices.RemoveAt(indices.Count - 1); } } // VerifyInternal(objs, dsObject, dsVariable, indices); } else if (expectedObject.GetType().IsArray) { object[] expectedArray = expectedObject as object[]; ProtoCore.DSASM.Mirror.DsasmArray dsArray = dsObject.Payload as ProtoCore.DSASM.Mirror.DsasmArray; if (dsArray == null) { Assert.Fail(String.Format("{0}{1} is expected to be an array, but its actual value isn't an array.\n{2}", dsVariable, BuildIndicesString(indices), mErrorMessage)); } else if (expectedArray.Count() != dsArray.members.Count()) { Assert.Fail(String.Format("{0}{1} is expected to be an array of length {2}, but its actual length is {3}.\n{4}", dsVariable, BuildIndicesString(indices), expectedArray.Count(), dsArray.members.Count(), mErrorMessage)); } else { for (int i = 0; i < expectedArray.Count(); ++i) { indices.Add(i); VerifyInternal(expectedArray[i], dsArray.members[i], dsVariable, indices); indices.RemoveAt(indices.Count - 1); } } } else { Assert.Fail(string.Format("\tUnexpected object type.\n{0}", mErrorMessage)); } }