/// <summary> /// array[index1][index2][...][indexN] = value, and /// indices = {index1, index2, ..., indexN} /// /// Note this function doesn't support the replication of array indexing. /// </summary> /// <param name="array"></param> /// <param name="indices"></param> /// <param name="value"></param> /// <param name="core"></param> /// <returns></returns> public static StackValue SetValueForIndices(StackValue array, StackValue[] indices, StackValue value, Core core) { Validity.Assert(StackUtils.IsArray(array) || StackUtils.IsString(array)); for (int i = 0; i < indices.Length - 1; ++i) { StackValue index = indices[i]; HeapElement he = GetHeapElement(array, core); StackValue subArray; if (StackUtils.IsNumeric(index)) { index = index.AsInt(); int absIndex = he.ExpandByAcessingAt((int)index.opdata); subArray = he.Stack[absIndex]; } else { subArray = GetValueFromIndex(array, index, core); } // auto-promotion if (!StackUtils.IsArray(subArray)) { subArray = HeapUtils.StoreArray(new StackValue[] { subArray }, null, core); GCUtils.GCRetain(subArray, core); SetValueForIndex(array, index, subArray, core); } array = subArray; } return(SetValueForIndex(array, indices[indices.Length - 1], value, core)); }
/// <summary> /// = array[index1][index2][...][indexN], and /// indices = {index1, index2, ..., indexN} /// /// Note this function doesn't support the replication of array indexing. /// </summary> /// <param name="array"></param> /// <param name="indices"></param> /// <param name="core"></param> /// <returns></returns> public static StackValue GetValueFromIndices(StackValue array, StackValue[] indices, Core core) { Validity.Assert(StackUtils.IsArray(array) || StackUtils.IsString(array)); for (int i = 0; i < indices.Length - 1; ++i) { if (!StackUtils.IsArray(array) && !StackUtils.IsString(array)) { core.RuntimeStatus.LogWarning(WarningID.kOverIndexing, WarningMessage.kArrayOverIndexed); return(StackUtils.BuildNull()); } StackValue index = indices[i]; if (StackUtils.IsNumeric(index)) { index = index.AsInt(); array = GetValueFromIndex(array, (int)index.opdata, core); } else { if (array.optype != AddressType.ArrayPointer) { core.RuntimeStatus.LogWarning(WarningID.kOverIndexing, WarningMessage.kArrayOverIndexed); return(StackUtils.BuildNull()); } array = GetValueFromIndex(array, index, core); } } return(GetValueFromIndex(array, indices[indices.Length - 1], core)); }
/// <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); } }
/// <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()); } } }
/// <summary> /// Return the element size of an array /// </summary> /// <param name="array"></param> /// <param name="core"></param> /// <returns></returns> public static int GetElementSize(StackValue array, Core core) { Validity.Assert(StackUtils.IsArray(array) || StackUtils.IsString(array)); if (!StackUtils.IsArray(array) && !StackUtils.IsString(array)) { return(Constants.kInvalidIndex); } return(GetHeapElement(array, core).VisibleSize); }
/// <summary> /// = array[index] /// </summary> /// <param name="array"></param> /// <param name="index"></param> /// <param name="core"></param> /// <returns></returns> public static StackValue GetValueFromIndex(StackValue array, int index, Core core) { Validity.Assert(StackUtils.IsArray(array) || StackUtils.IsString(array)); if (!StackUtils.IsArray(array) && !StackUtils.IsString(array)) { return(StackUtils.BuildNull()); } HeapElement he = GetHeapElement(array, core); return(StackUtils.GetValue(he, index, core)); }
/// <summary> /// array[index] = value. The array will be expanded if necessary. /// </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, int index, StackValue value, Core core) { Validity.Assert(StackUtils.IsArray(array) || StackUtils.IsString(array)); if (StackUtils.IsString(array) && value.optype != AddressType.Char) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeMismatch, RuntimeData.WarningMessage.kAssignNonCharacterToString); return(StackUtils.BuildNull()); } lock (core.Heap.cslock) { HeapElement arrayHeap = GetHeapElement(array, core); index = arrayHeap.ExpandByAcessingAt(index); StackValue oldValue = arrayHeap.SetValue(index, value); return(oldValue); } }
/// <summary> /// = array[index1][index2][...][indexN], and /// indices = {index1, index2, ..., indexN} /// </summary> /// <param name="array"></param> /// <param name="indices"></param> /// <param name="core"></param> /// <returns></returns> public static StackValue GetValueFromIndices(StackValue array, List <StackValue> indices, Core core) { if (indices.Count == 0) { return(array); } else if (!StackUtils.IsArray(array) && !StackUtils.IsString(array)) { core.RuntimeStatus.LogWarning(WarningID.kOverIndexing, WarningMessage.kArrayOverIndexed); return(StackUtils.BuildNull()); } StackValue[][] zippedIndices = ArrayUtils.GetZippedIndices(indices, core); if (zippedIndices == null || zippedIndices.Length == 0) { return(StackUtils.BuildNull()); } StackValue[] values = new StackValue[zippedIndices.Length]; for (int i = 0; i < zippedIndices.Length; ++i) { values[i] = GetValueFromIndices(array, zippedIndices[i], core); } if (zippedIndices.Length > 1) { for (int i = 0; i < values.Length; ++i) { GCUtils.GCRelease(values[i], core); } return(HeapUtils.StoreArray(values, null, core)); } else { return(values[0]); } }
public static int CompareString(StackValue s1, StackValue s2, Core core) { if (!StackUtils.IsString(s1) || !StackUtils.IsString(s2)) { return(ProtoCore.DSASM.Constants.kInvalidIndex); } HeapElement he1 = ArrayUtils.GetHeapElement(s1, core); HeapElement he2 = ArrayUtils.GetHeapElement(s2, core); int len1 = he1.VisibleSize; int len2 = he2.VisibleSize; int len = len1 > len2 ? len2 : len1; int i = 0; for (; i < len; ++i) { if (he1.Stack[i].opdata != he2.Stack[i].opdata) { return((he1.Stack[i].opdata > he2.Stack[i].opdata) ? 1 : -1); } } if (len1 > len2) { return(1); } else if (len1 == len2) { return(0); } else { return(-1); } }