/// <summary> /// Generate type statistics for given layer of an array /// </summary> /// <param name="array"></param> /// <returns></returns> public static Dictionary <ClassNode, int> GetTypeStatisticsForLayer(StackValue array, Core core) { if (!StackUtils.IsArray(array)) { Dictionary <ClassNode, int> ret = new Dictionary <ClassNode, int>(); ret.Add(core.DSExecutable.classTable.ClassNodes[(int)array.metaData.type], 1); return(ret); } Dictionary <ClassNode, int> usageFreq = new Dictionary <ClassNode, int>(); //This is the element on the heap that manages the data structure HeapElement heapElement = GetHeapElement(array, core); for (int i = 0; i < heapElement.VisibleSize; ++i) { StackValue sv = heapElement.Stack[i]; ClassNode cn = core.DSExecutable.classTable.ClassNodes[(int)sv.metaData.type]; if (!usageFreq.ContainsKey(cn)) { usageFreq.Add(cn, 0); } usageFreq[cn] = usageFreq[cn] + 1; } return(usageFreq); }
public static Dictionary <int, StackValue> GetTypeExamplesForLayer(StackValue array, Core core) { if (!StackUtils.IsArray(array)) { Dictionary <int, StackValue> ret = new Dictionary <int, StackValue>(); ret.Add((int)array.metaData.type, array); return(ret); } Dictionary <int, StackValue> usageFreq = new Dictionary <int, StackValue>(); //This is the element on the heap that manages the data structure HeapElement heapElement = GetHeapElement(array, core); for (int i = 0; i < heapElement.VisibleSize; ++i) { StackValue sv = heapElement.Stack[i]; if (!usageFreq.ContainsKey((int)sv.metaData.type)) { usageFreq.Add((int)sv.metaData.type, sv); } } return(usageFreq); }
/// <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); } }
private static int GetMaxRankForArray(StackValue array, Core core, int tracer) { if (tracer > RECURSION_LIMIT) { throw new CompilerInternalException("Internal Recursion limit exceeded in Rank Check - Possible heap corruption {3317D4F6-4758-4C19-9680-75B68DA0436D}"); } if (!StackUtils.IsArray(array)) { return(0); } //throw new ArgumentException("The stack value provided was not an array"); int ret = 1; //This is the element on the heap that manages the data structure HeapElement heapElement = GetHeapElement(array, core); int largestSub = 0; for (int i = 0; i < heapElement.VisibleSize; ++i) { StackValue sv = heapElement.Stack[i]; if (sv.optype == AddressType.ArrayPointer) { int subArrayRank = GetMaxRankForArray(sv, core, tracer + 1); largestSub = Math.Max(subArrayRank, largestSub); } } return(largestSub + ret); }
/// <summary> /// Gets all array elements in a List of given type using the given converter to /// convert the stackValue. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="array"></param> /// <param name="core"></param> /// <param name="converter"></param> /// <returns></returns> public static List <T> GetValues <T>(StackValue array, Core core, Func <StackValue, T> converter) { Validity.Assert(StackUtils.IsArray(array)); if (!StackUtils.IsArray(array)) { return(null); } HeapElement he = GetHeapElement(array, core); List <T> values = new List <T>(); foreach (var sv in he.Stack) { values.Add(converter(sv)); } if (he.Dict != null) { foreach (var sv in he.Dict.Values) { values.Add(converter(sv)); } } return(values); }
/// <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)); }
/* * [Obsolete] * public static StackValue CoerceArray(StackValue array, Type typ, Core core) * { * //@TODO(Luke) handle array rank coersions * * Validity.Assert(IsArray(array), "Argument needs to be an array {99FB71A6-72AD-4C93-8F1E-0B1F419C1A6D}"); * * //This is the element on the heap that manages the data structure * HeapElement heapElement = GetHeapElement(array, core); * StackValue[] newSVs = new StackValue[heapElement.VisibleSize]; * * for (int i = 0; i < heapElement.VisibleSize; ++i) * { * StackValue sv = heapElement.Stack[i]; * StackValue coercedValue; * * if (IsArray(sv)) * { * Type typ2 = new Type(); * typ2.UID = typ.UID; * typ2.rank = typ.rank - 1; * typ2.IsIndexable = (typ2.rank == -1 || typ2.rank > 0); * * coercedValue = CoerceArray(sv, typ2, core); * } * else * { * coercedValue = TypeSystem.Coerce(sv, typ, core); * } * * GCUtils.GCRetain(coercedValue, core); * newSVs[i] = coercedValue; * } * * return HeapUtils.StoreArray(newSVs, core); * } */ /// <summary> /// Retrieve the first non-array element in an array /// </summary> /// <param name="svArray"></param> /// <param name="sv"></param> /// <param name="core"></param> /// <returns> true if the element was found </returns> public static bool GetFirstNonArrayStackValue(StackValue svArray, ref StackValue sv, Core core) { if (AddressType.ArrayPointer != svArray.optype) { return(false); } int ptr = (int)svArray.opdata; if (null == core.Rmem.Heap.Heaplist[ptr].Stack || core.Rmem.Heap.Heaplist[ptr].Stack.Length == 0) { return(false); } while (StackUtils.IsArray(core.Rmem.Heap.Heaplist[ptr].Stack[0])) { ptr = (int)core.Rmem.Heap.Heaplist[ptr].Stack[0].opdata; // Handle the case where the array is valid but empty if (core.Rmem.Heap.Heaplist[ptr].Stack.Length == 0) { return(false); } } sv.optype = core.Rmem.Heap.Heaplist[ptr].Stack[0].optype; sv.opdata = core.Rmem.Heap.Heaplist[ptr].Stack[0].opdata; sv.metaData = core.Rmem.Heap.Heaplist[ptr].Stack[0].metaData; return(true); }
/// <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> /// Get all keys from an array /// </summary> /// <param name="array"></param> /// <param name="core"></param> /// <returns></returns> public static StackValue[] GetKeys(StackValue array, Core core) { Validity.Assert(StackUtils.IsArray(array)); if (!StackUtils.IsArray(array)) { return(null); } HeapElement he = GetHeapElement(array, core); List <StackValue> keys = new List <StackValue>(); for (int i = 0; i < he.VisibleSize; ++i) { keys.Add(StackUtils.BuildInt(i)); } if (he.Dict != null) { foreach (var key in he.Dict.Keys) { keys.Add(key); } } return(keys.ToArray()); }
internal int ComputeCastDistance(List <StackValue> args, ClassTable classTable, Core core) { //Compute the cost to migrate a class calls argument types to the coresponding base types //This cannot be used to determine whether a function can be called as it will ignore anything that doesn't //it should only be used to determine which class is closer if (args.Count != FormalParams.Length) { return(int.MaxValue); } int distance = 0; if (0 == args.Count) { return(distance); } else { // Check if all the types match the current function at 'n' for (int i = 0; i < args.Count; ++i) { int rcvdType = (int)args[i].metaData.type; // If its a default argumnet, then it wasnt provided by the caller // The rcvdType is the type of the argument signature if (args[i].optype == AddressType.DefaultArg) { rcvdType = FormalParams[i].UID; } int expectedType = FormalParams[i].UID; int currentCost = 0; if (FormalParams[i].IsIndexable != StackUtils.IsArray(args[i])) //Replication code will take care of this { continue; } else if (FormalParams[i].IsIndexable && (FormalParams[i].IsIndexable == StackUtils.IsArray(args[i]))) { continue; } else if (expectedType == rcvdType && (FormalParams[i].IsIndexable == StackUtils.IsArray(args[i]))) { continue; } else if (rcvdType != ProtoCore.DSASM.Constants.kInvalidIndex && expectedType != ProtoCore.DSASM.Constants.kInvalidIndex) { currentCost += ClassUtils.GetUpcastCountTo(classTable.ClassNodes[rcvdType], classTable.ClassNodes[expectedType], core); } distance += currentCost; } return(distance); } }
/// <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()); } } }
public static int GetFullSize(StackValue array, Core core) { Validity.Assert(StackUtils.IsArray(array)); if (!StackUtils.IsArray(array)) { return(Constants.kInvalidIndex); } return(GetElementSize(array, core) + GetValueSize(array, core)); }
/// <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)); if (!StackUtils.IsArray(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)); }
public static bool IsUniform(StackValue sv, Core core) { if (!StackUtils.IsArray(sv)) { return(false); } if (Utils.ArrayUtils.GetTypeStatisticsForArray(sv, core).Count != 1) { return(false); } return(true); }
private static StackValue[] GetFlattenValue(StackValue array, Core core) { Queue <StackValue> workingSet = new Queue <StackValue>(); List <StackValue> flattenValues = new List <StackValue>(); if (!StackUtils.IsArray(array)) { return(null); } workingSet.Enqueue(array); while (workingSet.Count > 0) { array = workingSet.Dequeue(); HeapElement he = GetHeapElement(array, core); for (int i = 0; i < he.VisibleSize; ++i) { StackValue value = he.Stack[i]; if (StackUtils.IsArray(value)) { workingSet.Enqueue(value); } else { flattenValues.Add(value); } } if (he.Dict != null) { foreach (var value in he.Dict.Values) { if (StackUtils.IsArray(value)) { workingSet.Enqueue(value); } else { flattenValues.Add(value); } } } } return(flattenValues.ToArray()); }
/// <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> /// Generate type statistics for the whole array /// </summary> /// <param name="array"></param> /// <param name="core"></param> /// <returns></returns> public static Dictionary <ClassNode, int> GetTypeStatisticsForArray(StackValue array, Core core) { if (!StackUtils.IsArray(array)) { Dictionary <ClassNode, int> ret = new Dictionary <ClassNode, int>(); ret.Add(core.ClassTable.ClassNodes[(int)array.metaData.type], 1); return(ret); } Dictionary <ClassNode, int> usageFreq = new Dictionary <ClassNode, int>(); //This is the element on the heap that manages the data structure HeapElement heapElement = GetHeapElement(array, core); for (int i = 0; i < heapElement.VisibleSize; ++i) { StackValue sv = heapElement.Stack[i]; if (sv.optype == AddressType.ArrayPointer) { //Recurse Dictionary <ClassNode, int> subLayer = GetTypeStatisticsForArray(sv, core); foreach (ClassNode cn in subLayer.Keys) { if (!usageFreq.ContainsKey(cn)) { usageFreq.Add(cn, 0); } usageFreq[cn] = usageFreq[cn] + subLayer[cn]; } } else { ClassNode cn = core.ClassTable.ClassNodes[(int)sv.metaData.type]; if (!usageFreq.ContainsKey(cn)) { usageFreq.Add(cn, 0); } usageFreq[cn] = usageFreq[cn] + 1; } } return(usageFreq); }
/// <summary> /// If the passed in value is not an array or an empty array or an array which contains only empty arrays, return false. /// Otherwise, return true; /// </summary> /// <param name="sv"></param> /// <param name="core"></param> /// <returns></returns> public static bool ContainsNonArrayElement(StackValue sv, Core core) { if (!StackUtils.IsArray(sv)) { return(true); } StackValue[] svArray = core.Rmem.GetArrayElements(sv); foreach (var item in svArray) { if (ContainsNonArrayElement(item, core)) { return(true); } } return(false); }
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); }
/* * [Obsolete] * public static StackValue CoerceArray(StackValue array, Type typ, Core core) * { * //@TODO(Luke) handle array rank coersions * * Validity.Assert(IsArray(array), "Argument needs to be an array {99FB71A6-72AD-4C93-8F1E-0B1F419C1A6D}"); * * //This is the element on the heap that manages the data structure * HeapElement heapElement = GetHeapElement(array, core); * StackValue[] newSVs = new StackValue[heapElement.VisibleSize]; * * for (int i = 0; i < heapElement.VisibleSize; ++i) * { * StackValue sv = heapElement.Stack[i]; * StackValue coercedValue; * * if (IsArray(sv)) * { * Type typ2 = new Type(); * typ2.UID = typ.UID; * typ2.rank = typ.rank - 1; * typ2.IsIndexable = (typ2.rank == -1 || typ2.rank > 0); * * coercedValue = CoerceArray(sv, typ2, core); * } * else * { * coercedValue = TypeSystem.Coerce(sv, typ, core); * } * * GCUtils.GCRetain(coercedValue, core); * newSVs[i] = coercedValue; * } * * return HeapUtils.StoreArray(newSVs, core); * } */ // Retrieve the first non-array element in an array public static bool GetFirstNonArrayStackValue(StackValue svArray, ref StackValue sv, Core core) { if (AddressType.ArrayPointer != svArray.optype) { return(false); } int ptr = (int)svArray.opdata; while (StackUtils.IsArray(core.Rmem.Heap.Heaplist[ptr].Stack[0])) { ptr = (int)core.Rmem.Heap.Heaplist[ptr].Stack[0].opdata; } sv.optype = core.Rmem.Heap.Heaplist[ptr].Stack[0].optype; sv.opdata = core.Rmem.Heap.Heaplist[ptr].Stack[0].opdata; sv.metaData = core.Rmem.Heap.Heaplist[ptr].Stack[0].metaData; return(true); }
public static int GetValueSize(StackValue array, Core core) { Validity.Assert(StackUtils.IsArray(array)); if (!StackUtils.IsArray(array)) { return(Constants.kInvalidIndex); } HeapElement he = GetHeapElement(array, core); if (null == he) { return(0); } var dict = he.Dict as Dictionary <StackValue, StackValue>; return((null == dict) ? 0 : dict.Count); }
/// <summary> /// Copy an array and coerce its elements/values to target type /// </summary> /// <param name="array"></param> /// <param name="type"></param> /// <param name="core"></param> /// <returns></returns> public static StackValue CopyArray(StackValue array, Type type, Core core) { Validity.Assert(StackUtils.IsArray(array)); if (!StackUtils.IsArray(array)) { return(StackUtils.BuildNull()); } HeapElement he = GetHeapElement(array, core); Validity.Assert(he != null); int elementSize = GetElementSize(array, core); StackValue[] elements = new StackValue[elementSize]; for (int i = 0; i < elementSize; i++) { StackValue coercedValue = TypeSystem.Coerce(he.Stack[i], type, core); GCUtils.GCRetain(coercedValue, core); elements[i] = coercedValue; } Dictionary <StackValue, StackValue> dict = null; if (he.Dict != null) { dict = new Dictionary <StackValue, StackValue>(new StackValueComparer(core)); foreach (var pair in he.Dict) { StackValue key = pair.Key; StackValue value = pair.Value; StackValue coercedValue = TypeSystem.Coerce(value, type, core); GCUtils.GCRetain(key, core); GCUtils.GCRetain(coercedValue, core); dict[key] = coercedValue; } } return(HeapUtils.StoreArray(elements, dict, core)); }
///// <summary> ///// Get the maximum depth to which an object can be reduced ///// </summary> ///// <param name="obj"></param> ///// <returns></returns> //[Obsolete] //public static int GetMaxReductionDepth(ProtoCore.Lang.Obj obj) //{ // if (!obj.Type.IsIndexable) // return 0; // else // { // return 1 + GetMaxReductionDepth((Obj)((DSASM.Mirror.DsasmArray)obj.Payload).members[0]); // } //} /// <summary> /// Get the maximum depth to which an element can be reduced /// This will include cases where only partial reduction can be performed on jagged arrays /// </summary> /// <param name="sv"></param> /// <param name="core"></param> /// <returns></returns> public static int GetMaxReductionDepth(StackValue sv, Core core) { //PERF(Luke): Could be non-recursive if (!StackUtils.IsArray(sv)) { return(0); } int maxReduction = 0; //De-ref the sv HeapElement he = ProtoCore.Utils.ArrayUtils.GetHeapElement(sv, core); for (int i = 0; i < he.VisibleSize; ++i) { StackValue subSv = he.Stack[i]; maxReduction = Math.Max(maxReduction, GetMaxReductionDepth(subSv, core)); } return(1 + maxReduction); }
/// <summary> /// Get all values from an array. /// </summary> /// <param name="array"></param> /// <param name="core"></param> /// <returns></returns> public static StackValue[] GetValues(StackValue array, Core core) { Validity.Assert(StackUtils.IsArray(array)); if (!StackUtils.IsArray(array)) { return(null); } HeapElement he = GetHeapElement(array, core); List <StackValue> values = new List <StackValue>(he.Stack); if (he.Dict != null) { foreach (var value in he.Dict.Values) { values.Add(value); } } return(values.ToArray()); }
/// <summary> /// Tests whether this end point matches the type of the passed arguments /// </summary> /// <param name="formalParameters">The proposed parameters </param> /// <returns></returns> public bool DoesTypeMatch(List <StackValue> formalParameters) { if (formalParameters.Count != FormalParams.Length) { return(false); } for (int i = 0; i < FormalParams.Length; i++) { if (FormalParams[i].IsIndexable && StackUtils.IsArray(formalParameters[i])) { continue; } if (FormalParams[i].UID != (int)formalParameters[i].metaData.type) { return(false); } } return(true); }
public void IsArrayTest() { String code = @"a;b;c; [Imperative] { a = {1,2,3}; b = 1; c = a; } "; ProtoScript.Runners.ProtoScriptTestRunner fsr = new ProtoScript.Runners.ProtoScriptTestRunner(); ExecutionMirror mirror = fsr.Execute(code, core); StackValue svA = mirror.GetRawFirstValue("a"); StackValue svB = mirror.GetRawFirstValue("b"); StackValue svC = mirror.GetRawFirstValue("c"); Assert.IsTrue(StackUtils.IsArray(svA)); Assert.IsTrue(!StackUtils.IsArray(svB)); Assert.IsTrue(StackUtils.IsArray(svC)); }
/// <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]); } }
/// <summary> /// Whether sv is double or arrays contains double value. /// </summary> /// <param name="sv"></param> /// <param name="core"></param> /// <returns></returns> public static bool ContainsDoubleElement(StackValue sv, Core core) { if (!StackUtils.IsArray(sv)) { return(core.TypeSystem.GetType(sv) == (int)PrimitiveType.kTypeDouble); } StackValue[] svArray = core.Rmem.GetArrayElements(sv); foreach (var item in svArray) { if (StackUtils.IsArray(item) && ContainsDoubleElement(item, core)) { return(true); } if (core.TypeSystem.GetType(item) == (int)PrimitiveType.kTypeDouble) { return(true); } } return(false); }
/// <summary> /// This computes the max depth to which the element can be reduced /// It contains a protected envelope /// </summary> /// <param name="sv"></param> /// <param name="core"></param> /// <param name="depthCount"></param> /// <returns></returns> private static int RecursiveProtectGetMaxReductionDepth(StackValue sv, Core core, int depthCount) { Validity.Assert(depthCount < 1000, "StackOverflow protection trap. This is almost certainly a VM cycle-in-array bug. {0B530165-2E38-431D-88D9-56B0636364CD}"); //PERF(Luke): Could be non-recursive if (!StackUtils.IsArray(sv)) { return(0); } int maxReduction = 0; //De-ref the sv HeapElement he = ProtoCore.Utils.ArrayUtils.GetHeapElement(sv, core); for (int i = 0; i < he.VisibleSize; ++i) { StackValue subSv = he.Stack[i]; maxReduction = Math.Max(maxReduction, RecursiveProtectGetMaxReductionDepth(subSv, core, depthCount + 1)); } return(1 + maxReduction); }