//@TODO: Factor this into the type system public static StackValue ClassCoerece(StackValue sv, Type targetType, Core core) { //@TODO: Add proper coersion testing here. if (targetType.UID == (int)PrimitiveType.kTypeBool) { return(StackUtils.BuildBoolean(true)); } return(sv.ShallowClone()); }
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"); }
public static StackValue Coerce(StackValue sv, Type targetType, RuntimeCore runtimeCore) { ProtoCore.Runtime.RuntimeMemory rmem = runtimeCore.RuntimeMemory; //@TODO(Jun): FIX ME - abort coersion for default args if (sv.IsDefaultArgument) { return(sv); } if (!( sv.metaData.type == targetType.UID || (runtimeCore.DSExecutable.classTable.ClassNodes[sv.metaData.type].ConvertibleTo(targetType.UID)) || sv.IsArray)) { runtimeCore.RuntimeStatus.LogWarning(Runtime.WarningID.ConversionNotPossible, Resources.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(Resources.kConvertArrayToNonArray, runtimeCore.DSExecutable.TypeSystem.GetType(targetType.UID)); runtimeCore.RuntimeStatus.LogWarning(Runtime.WarningID.ConversionNotPossible, 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 //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, runtimeCore) == 1) { //Last unpacking newTargetType.rank = 0; } else { newTargetType.rank = Constants.kArbitraryRank; } } var array = runtimeCore.Heap.ToHeapObject <DSArray>(sv); return(array.CopyArray(newTargetType, runtimeCore)); } 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, runtimeCore); try { StackValue newSv = rmem.Heap.AllocateArray(new StackValue[] { coercedValue }); return(newSv); } catch (RunOutOfMemoryException) { runtimeCore.RuntimeStatus.LogWarning(Runtime.WarningID.RunOutOfMemory, Resources.RunOutOfMemory); return(StackValue.Null); } } 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, runtimeCore); try { StackValue newSv = rmem.Heap.AllocateArray(new StackValue[] { coercedValue }); return(newSv); } catch (RunOutOfMemoryException) { runtimeCore.RuntimeStatus.LogWarning(Runtime.WarningID.RunOutOfMemory, Resources.RunOutOfMemory); return(StackValue.Null); } } } if (sv.IsPointer) { StackValue ret = ClassCoerece(sv, targetType, runtimeCore); return(ret); } //If it's anything other than array, just create a new copy switch (targetType.UID) { case (int)PrimitiveType.InvalidType: runtimeCore.RuntimeStatus.LogWarning(Runtime.WarningID.InvalidType, Resources.kInvalidType); return(StackValue.Null); case (int)PrimitiveType.Bool: return(sv.ToBoolean(runtimeCore)); case (int)PrimitiveType.Char: { StackValue newSV = sv.ShallowClone(); newSV.metaData = new MetaData { type = (int)PrimitiveType.Char }; return(newSV); } case (int)PrimitiveType.Double: return(sv.ToDouble()); case (int)PrimitiveType.FunctionPointer: if (sv.metaData.type != (int)PrimitiveType.FunctionPointer) { runtimeCore.RuntimeStatus.LogWarning(Runtime.WarningID.TypeMismatch, Resources.kFailToConverToFunction); return(StackValue.Null); } return(sv); case (int)PrimitiveType.Integer: { if (sv.metaData.type == (int)PrimitiveType.Double) { //TODO(lukechurch): Once the API is improved (MAGN-5174) //Replace this with a log entry notification //core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeConvertionCauseInfoLoss, Resources.kConvertDoubleToInt); } return(sv.ToInteger()); } case (int)PrimitiveType.Null: { if (sv.metaData.type != (int)PrimitiveType.Null) { runtimeCore.RuntimeStatus.LogWarning(Runtime.WarningID.TypeMismatch, Resources.kFailToConverToNull); return(StackValue.Null); } return(sv); } case (int)PrimitiveType.Pointer: { if (sv.metaData.type != (int)PrimitiveType.Null) { runtimeCore.RuntimeStatus.LogWarning(Runtime.WarningID.TypeMismatch, Resources.kFailToConverToPointer); return(StackValue.Null); } return(sv); } case (int)PrimitiveType.String: { StackValue newSV = sv.ShallowClone(); newSV.metaData = new MetaData { type = (int)PrimitiveType.String }; if (sv.metaData.type == (int)PrimitiveType.Char) { char ch = Convert.ToChar(newSV.CharValue); newSV = StackValue.BuildString(ch.ToString(), rmem.Heap); } return(newSV); } case (int)PrimitiveType.Var: { return(sv); } case (int)PrimitiveType.Array: { var array = runtimeCore.Heap.ToHeapObject <DSArray>(sv); return(array.CopyArray(targetType, runtimeCore)); } default: if (sv.IsNull) { return(StackValue.Null); } else { throw new NotImplementedException("Requested coercion not implemented"); } } }
public static StackValue Coerce(StackValue sv, Type targetType, Core core) { //@TODO(Jun): FIX ME - abort coersion for default args if (sv.optype == AddressType.DefaultArg) { return(sv); } if (!( (int)sv.metaData.type == targetType.UID || (core.DSExecutable.classTable.ClassNodes[(int)sv.metaData.type].ConvertibleTo(targetType.UID)) || sv.optype == AddressType.ArrayPointer)) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kConversionNotPossible, ProtoCore.RuntimeData.WarningMessage.kConvertNonConvertibleTypes); return(StackUtils.BuildNull()); } //if it's an array if (sv.optype == AddressType.ArrayPointer && !targetType.IsIndexable && targetType.rank != DSASM.Constants.kUndefinedRank)// && targetType.UID != (int)PrimitiveType.kTypeVar) { //This is an array rank reduction //this may only be performed in recursion and is illegal here string errorMessage = String.Format(ProtoCore.RuntimeData.WarningMessage.kConvertArrayToNonArray, core.TypeSystem.GetType(targetType.UID)); core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kConversionNotPossible, errorMessage); return(StackUtils.BuildNull()); } if (sv.optype == AddressType.ArrayPointer && targetType.IsIndexable) { Validity.Assert(ArrayUtils.IsArray(sv)); //We're being asked to convert an array into an array //walk over the structure converting each othe elements if (targetType.UID == (int)PrimitiveType.kTypeVar && targetType.rank == DSASM.Constants.kArbitraryRank && core.Heap.IsTemporaryPointer(sv)) { return(sv); } HeapElement he = core.Heap.Heaplist[(int)sv.opdata]; StackValue[] newSubSVs = new StackValue[he.VisibleSize]; //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 != ProtoCore.DSASM.Constants.kArbitraryRank) { newTargetType.rank = targetType.rank - 1; newTargetType.IsIndexable = newTargetType.rank > 0; } else { if (ArrayUtils.GetMaxRankForArray(sv, core) == 1) { //Last unpacking newTargetType.rank = 0; newTargetType.IsIndexable = false; } else { newTargetType.rank = ProtoCore.DSASM.Constants.kArbitraryRank; newTargetType.IsIndexable = true; } } for (int i = 0; i < he.VisibleSize; i++) { StackValue coercedValue = Coerce(he.Stack[i], newTargetType, core); GCUtils.GCRetain(coercedValue, core); newSubSVs[i] = coercedValue; } StackValue newSV = HeapUtils.StoreArray(newSubSVs, core); return(newSV); } if (sv.optype != AddressType.ArrayPointer && sv.optype != AddressType.Null && 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.IsIndexable = false; newTargetType.Name = targetType.Name; newTargetType.rank = 0; //Upcast once StackValue coercedValue = Coerce(sv, newTargetType, core); GCUtils.GCRetain(coercedValue, core); StackValue newSv = HeapUtils.StoreArray(new StackValue[] { coercedValue }, core); 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.IsIndexable = true; newTargetType.Name = targetType.Name; newTargetType.rank = targetType.rank - 1; //Upcast once StackValue coercedValue = Coerce(sv, newTargetType, core); GCUtils.GCRetain(coercedValue, core); StackValue newSv = HeapUtils.StoreArray(new StackValue[] { coercedValue }, core); return(newSv); } } if (sv.optype == AddressType.Pointer) { 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.AsBoolean(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.AsDouble()); case (int)PrimitiveType.kTypeFunctionPointer: if (sv.metaData.type != (int)PrimitiveType.kTypeFunctionPointer) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeMismatch, ProtoCore.RuntimeData.WarningMessage.kFailToConverToFunction); return(StackUtils.BuildNull()); } return(sv.ShallowClone()); 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) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeConvertionCauseInfoLoss, ProtoCore.RuntimeData.WarningMessage.kConvertDoubleToInt); } return(sv.AsInt()); } case (int)PrimitiveType.kTypeNull: { if (sv.metaData.type != (int)PrimitiveType.kTypeNull) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeMismatch, ProtoCore.RuntimeData.WarningMessage.kFailToConverToNull); return(StackUtils.BuildNull()); } return(sv.ShallowClone()); } case (int)PrimitiveType.kTypePointer: { if (sv.metaData.type != (int)PrimitiveType.kTypeNull) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeMismatch, ProtoCore.RuntimeData.WarningMessage.kFailToConverToPointer); return(StackUtils.BuildNull()); } StackValue ret = sv.ShallowClone(); return(ret); } 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 = ProtoCore.Utils.EncodingUtils.ConvertInt64ToCharacter(newSV.opdata); newSV = StackUtils.BuildString(ch.ToString(), core.Heap); } return(newSV); } case (int)PrimitiveType.kTypeVar: { return(sv); } case (int)PrimitiveType.kTypeArray: { HeapElement he = core.Heap.Heaplist[(int)sv.opdata]; StackValue[] newSubSVs = new StackValue[he.VisibleSize]; for (int i = 0; i < he.VisibleSize; i++) { StackValue coercedValue = Coerce(he.Stack[i], targetType, core); GCUtils.GCRetain(coercedValue, core); newSubSVs[i] = coercedValue; } StackValue newSV = HeapUtils.StoreArray(newSubSVs, core); return(newSV); } default: if (sv.optype == AddressType.Null) { return(StackUtils.BuildNull()); } else { throw new NotImplementedException("Requested coercion not implemented"); } } throw new NotImplementedException("Requested coercion not implemented"); }