/// <summary> /// Check if an array contain key /// </summary> /// <param name="array"></param> /// <param name="key"></param> /// <param name="core"></param> /// <returns></returns> public static bool ContainsKey(StackValue array, StackValue key, Core core) { Validity.Assert(StackUtils.IsArray(array)); if (!StackUtils.IsArray(array)) { return false; } HeapElement he = GetHeapElement(array, core); if (StackUtils.IsNumeric(key)) { long index = key.AsInt().opdata; if (index < 0) { index = index + he.VisibleSize; } return (index >= 0 && index < he.VisibleSize); } else { return he.Dict != null && he.Dict.ContainsKey(key); } }
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"); }
/// <summary> /// array[index] = value. Here index can be any type. /// /// Note this function doesn't support the replication of array indexing. /// </summary> /// <param name="array"></param> /// <param name="index"></param> /// <param name="value"></param> /// <param name="core"></param> /// <returns></returns> public static StackValue SetValueForIndex(StackValue array, StackValue index, StackValue value, Core core) { Validity.Assert(StackUtils.IsArray(array) || StackUtils.IsString(array)); if (StackUtils.IsNumeric(index)) { index = index.AsInt(); return SetValueForIndex(array, (int)index.opdata, value, core); } else { HeapElement he = GetHeapElement(array, core); if (he.Dict == null) { he.Dict = new Dictionary<StackValue, StackValue>(new StackValueComparer(core)); } StackValue oldValue; if (!he.Dict.TryGetValue(index, out oldValue)) { oldValue = StackUtils.BuildNull(); } GCUtils.GCRetain(index, core); GCUtils.GCRetain(value, core); he.Dict[index] = value; return oldValue; } }
public static bool RemoveKey(StackValue array, StackValue key, Core core) { Validity.Assert(StackUtils.IsArray(array)); if (!StackUtils.IsArray(array)) { return false; } HeapElement he = GetHeapElement(array, core); if (StackUtils.IsNumeric(key)) { long index = key.AsInt().opdata; if (index < 0) { index = index + he.VisibleSize; } if (index >= 0 && index < he.VisibleSize) { StackValue oldValue = he.Stack[index]; he.Stack[index] = StackUtils.BuildNull(); if (index == he.VisibleSize - 1) { he.VisibleSize -= 1; } return true; } } else { if (he.Dict != null && he.Dict.ContainsKey(key)) { StackValue value = he.Dict[key]; GCUtils.GCRelease(key, core); GCUtils.GCRelease(value, core); he.Dict.Remove(key); return true; } } return false; }
/// <summary> /// = array[index]. /// /// Note this function doesn't support the replication of array indexing. /// </summary> /// <param name="array"></param> /// <param name="index"></param> /// <param name="core"></param> /// <returns></returns> public static StackValue GetValueFromIndex(StackValue array, StackValue index, Core core) { Validity.Assert(StackUtils.IsArray(array) || StackUtils.IsString(array)); if (!StackUtils.IsArray(array) && !StackUtils.IsString(array)) { return StackUtils.BuildNull(); } if (StackUtils.IsNumeric(index)) { index = index.AsInt(); return GetValueFromIndex(array, (int)index.opdata, core); } else if (index.optype == AddressType.ArrayKey) { int fullIndex = (int)index.opdata; HeapElement he = GetHeapElement(array, core); if (he.VisibleSize > fullIndex) { return GetValueFromIndex(array, fullIndex, core); } else { fullIndex = fullIndex - he.VisibleSize; if (he.Dict != null && he.Dict.Count > fullIndex) { int count = 0; foreach (var key in he.Dict.Keys) { if (count == fullIndex) { return he.Dict[key]; } count = count + 1; } } } return StackUtils.BuildNull(); } else { HeapElement he = GetHeapElement(array, core); StackValue value = StackUtils.BuildNull(); if (he.Dict != null && he.Dict.TryGetValue(index, out value)) { return value; } else { return StackUtils.BuildNull(); } } }