public static bool CompareFromDifferentCore(DSArray array1, DSArray array2, RuntimeCore rtCore1, RuntimeCore rtCore2, Context context = null) { if (array1.Count != array2.Count) { return(false); } for (int i = 0; i < array1.Count; i++) { if (!StackUtils.CompareStackValues(array1.GetValueAt(i), array2.GetValueAt(i), rtCore1, rtCore2, context)) { return(false); } } foreach (var key in array1.Dict.Keys) { StackValue value1 = array1.Dict[key]; StackValue value2 = StackValue.Null; if (!array2.Dict.TryGetValue(key, out value2)) { return(false); } if (!StackUtils.CompareStackValues(value1, value2, rtCore1, rtCore2)) { return(false); } } return(true); }
/// <summary> /// Get an array's next key /// </summary> /// <param name="key"></param> /// <param name="core"></param> /// <returns></returns> public StackValue GetNextKey(RuntimeCore runtimeCore) { StackValue svArray; int index; if (!TryGetArrayKey(out svArray, out index)) { return(StackValue.Null); } int nextIndex = Constants.kInvalidIndex; if (svArray.IsArray) { DSArray array = runtimeCore.Heap.ToHeapObject <DSArray>(svArray); if (array.Values.Count() > index + 1) { nextIndex = index + 1; } } else if (svArray.IsString) { DSString str = runtimeCore.Heap.ToHeapObject <DSString>(svArray); if (str.Value.Length > index + 1) { nextIndex = index + 1; } } return(nextIndex == Constants.kInvalidIndex ? StackValue.Null : StackValue.BuildArrayKey(svArray, nextIndex)); }
/// <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 StackValue GetValueFromIndices(StackValue[] indices, RuntimeCore runtimeCore) { DSArray array = this; for (int i = 0; i < indices.Length - 1; ++i) { StackValue index = indices[i]; StackValue svArray = StackValue.Null; if (index.IsNumeric) { index = index.ToInteger(); svArray = array.GetValueFromIndex((int)index.IntegerValue, runtimeCore); } else { svArray = array.GetValueFromIndex(index, runtimeCore); } if (!svArray.IsArray) { runtimeCore.RuntimeStatus.LogWarning(WarningID.OverIndexing, Resources.kArrayOverIndexed); return(StackValue.Null); } array = heap.ToHeapObject <DSArray>(svArray); } return(array.GetValueFromIndex(indices[indices.Length - 1], runtimeCore)); }
/// <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="indices"></param> /// <param name="value"></param> /// <param name="core"></param> /// <returns></returns> public StackValue SetValueForIndices(StackValue[] indices, StackValue value, RuntimeCore runtimeCore) { DSArray array = this; for (int i = 0; i < indices.Length - 1; ++i) { StackValue index = indices[i]; StackValue svSubArray; if (index.IsNumeric) { index = index.ToInteger(); int absIndex = array.ExpandByAcessingAt((int)index.opdata); svSubArray = array.GetValueAt(absIndex); } else { svSubArray = array.GetValueFromIndex(index, runtimeCore); } // auto-promotion if (!svSubArray.IsArray) { svSubArray = heap.AllocateArray(new StackValue[] { svSubArray }); array.SetValueForIndex(index, svSubArray, runtimeCore); } array = heap.ToHeapObject <DSArray>(svSubArray); } return(array.SetValueForIndex(indices[indices.Length - 1], value, runtimeCore)); }
/// <summary> /// array[index1][index2][...][indexN] = value, and /// indices = {index1, index2, ..., indexN} /// </summary> /// <param name="indices"></param> /// <param name="value"></param> /// <param name="t"></param> /// <param name="core"></param> /// <returns></returns> public StackValue SetValueForIndices(List <StackValue> indices, StackValue value, Type t, RuntimeCore runtimeCore) { StackValue[][] zippedIndices = ArrayUtils.GetZippedIndices(indices, runtimeCore); if (zippedIndices == null || zippedIndices.Length == 0) { return(StackValue.Null); } if (zippedIndices.Length == 1) { StackValue coercedData = TypeSystem.Coerce(value, t, runtimeCore); return(SetValueForIndices(zippedIndices[0], coercedData, runtimeCore)); } if (t.rank > 0) { t.rank = t.rank - 1; } if (value.IsArray) { // Replication happens on both side. DSArray dataElements = heap.ToHeapObject <DSArray>(value); int length = Math.Min(zippedIndices.Length, dataElements.Count); StackValue[] oldValues = new StackValue[length]; for (int i = 0; i < length; ++i) { StackValue coercedData = TypeSystem.Coerce(dataElements.GetValueAt(i), t, runtimeCore); oldValues[i] = SetValueForIndices(zippedIndices[i], coercedData, runtimeCore); } // The returned old values shouldn't have any key-value pairs return(heap.AllocateArray(oldValues)); } else { // Replication is only on the LHS, so collect all old values // and return them in an array. StackValue coercedData = TypeSystem.Coerce(value, t, runtimeCore); StackValue[] oldValues = new StackValue[zippedIndices.Length]; for (int i = 0; i < zippedIndices.Length; ++i) { oldValues[i] = SetValueForIndices(zippedIndices[i], coercedData, runtimeCore); } // The returned old values shouldn't have any key-value pairs return(heap.AllocateArray(oldValues)); } }
/// <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="indices"></param> /// <param name="value"></param> /// <param name="core"></param> /// <returns></returns> public StackValue SetValueForIndices(StackValue[] indices, StackValue value, RuntimeCore runtimeCore) { DSArray array = this; for (int i = 0; i < indices.Length - 1; ++i) { StackValue index = indices[i]; StackValue svSubArray; if (index.IsNumeric) { index = index.ToInteger(); try { int absIndex = array.ExpandByAcessingAt((int)index.IntegerValue); svSubArray = array.GetValueAt(absIndex); } catch (RunOutOfMemoryException) { runtimeCore.RuntimeStatus.LogWarning(WarningID.RunOutOfMemory, Resources.RunOutOfMemory); return(StackValue.Null); } } else { svSubArray = array.GetValueFromIndex(index, runtimeCore); } // auto-promotion if (!svSubArray.IsArray) { try { svSubArray = heap.AllocateArray(new StackValue[] { svSubArray }); } catch (RunOutOfMemoryException) { svSubArray = StackValue.Null; runtimeCore.RuntimeStatus.LogWarning(WarningID.RunOutOfMemory, Resources.RunOutOfMemory); } array.SetValueForIndex(index, svSubArray, runtimeCore); } array = heap.ToHeapObject <DSArray>(svSubArray); } return(array.SetValueForIndex(indices[indices.Length - 1], value, runtimeCore)); }
/// <summary> /// Try to get value for key from nested dictionaries. This function is /// used in the case that indexing into dictionaries that returned from /// a replicated function whose return type is dictionary. /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="core"></param> /// <returns></returns> public bool TryGetValueFromNestedDictionaries(StackValue key, out StackValue value, RuntimeCore runtimeCore) { if (Dict != null && Dict.TryGetValue(key, out value)) { return(true); } var values = new List <StackValue>(); bool hasValue = false; foreach (var element in Values) { if (!(element.IsArray)) { continue; } StackValue valueInElement; DSArray subArray = heap.ToHeapObject <DSArray>(element); if (subArray.TryGetValueFromNestedDictionaries(key, out valueInElement, runtimeCore)) { hasValue = true; values.Add(valueInElement); } } if (hasValue) { try { value = heap.AllocateArray(values.ToArray()); return(true); } catch (RunOutOfMemoryException) { value = StackValue.Null; runtimeCore.RuntimeStatus.LogWarning(WarningID.RunOutOfMemory, Resources.RunOutOfMemory); return(false); } } else { value = StackValue.Null; return(false); } }
public static bool CompareFromDifferentCore(DSArray array1, DSArray array2, RuntimeCore rtCore1, RuntimeCore rtCore2, Context context = null) { if (array1.Count != array2.Count) { return(false); } for (int i = 0; i < array1.Count; i++) { if (!StackUtils.CompareStackValues(array1.GetValueAt(i), array2.GetValueAt(i), rtCore1, rtCore2, context)) { return(false); } } return(true); }
/// <summary> /// Mark all items in the array. /// </summary> /// <param name="array">Array</param> /// <returns>Return the size of memory that referenced by the array</returns> private int TraverseArray(DSArray array) { var dict = array.ToDictionary(); int size = array.MemorySize; foreach (var pair in array.ToDictionary()) { var key = pair.Key; if (key.IsReferenceType) size += RecursiveMark(key); var value = pair.Value; if (value.IsReferenceType) size += RecursiveMark(value); } return size; }
private int AllocateInternal(int size, PrimitiveType type) { switch (type) { case PrimitiveType.kTypeArray: var dsArray = new DSArray(size, this); return(AddHeapElement(dsArray)); case PrimitiveType.kTypePointer: var dsObject = new DSObject(size, this); return(AddHeapElement(dsObject)); case PrimitiveType.kTypeString: var dsString = new DSString(size, this); return(AddHeapElement(dsString)); default: throw new ArgumentException("type"); } }
/// <summary> /// Try to get value for key from nested dictionaries. This function is /// used in the case that indexing into dictionaries that returned from /// a replicated function whose return type is dictionary. /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="core"></param> /// <returns></returns> public bool TryGetValueFromNestedDictionaries(StackValue key, out StackValue value, RuntimeCore runtimeCore) { if (Dict != null && Dict.TryGetValue(key, out value)) { return(true); } var values = new List <StackValue>(); bool hasValue = false; foreach (var element in VisibleItems) { if (!(element.IsArray)) { continue; } StackValue valueInElement; DSArray subArray = heap.ToHeapObject <DSArray>(element); if (subArray.TryGetValueFromNestedDictionaries(key, out valueInElement, runtimeCore)) { hasValue = true; values.Add(valueInElement); } } if (hasValue) { value = heap.AllocateArray(values); return(true); } else { value = StackValue.Null; return(false); } }
private int AllocateInternal(StackValue[] values, PrimitiveType type) { HeapElement hpe = null; switch (type) { case PrimitiveType.Array: hpe = new DSArray(values, this); break; case PrimitiveType.Pointer: hpe = new DSObject(values, this); break; case PrimitiveType.String: hpe = new DSString(values, this); break; default: throw new ArgumentException("type"); } return(AddHeapElement(hpe)); }
private int AllocateInternal(int size, PrimitiveType type) { HeapElement hpe = null; switch (type) { case PrimitiveType.kTypeArray: hpe = new DSArray(size, this); break; case PrimitiveType.kTypePointer: hpe = new DSObject(size, this); break; case PrimitiveType.kTypeString: hpe = new DSString(size, this); break; default: throw new ArgumentException("type"); } return AddHeapElement(hpe); }
/// <summary> /// array[index1][index2][...][indexN] = value, and /// indices = {index1, index2, ..., indexN} /// </summary> /// <param name="indices"></param> /// <param name="value"></param> /// <param name="t"></param> /// <param name="core"></param> /// <returns></returns> public StackValue SetValueForIndices(List <StackValue> indices, StackValue value, RuntimeCore runtimeCore) { StackValue[][] zippedIndices = ArrayUtils.GetZippedIndices(indices, runtimeCore); if (zippedIndices == null || zippedIndices.Length == 0) { return(StackValue.Null); } var t = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.Var); if (zippedIndices.Length == 1) { StackValue coercedData = TypeSystem.Coerce(value, t, runtimeCore); return(SetValueForIndices(zippedIndices[0], coercedData, runtimeCore)); } if (value.IsArray) { // Replication happens on both side. DSArray dataElements = heap.ToHeapObject <DSArray>(value); int length = Math.Min(zippedIndices.Length, dataElements.Count); StackValue[] oldValues = new StackValue[length]; for (int i = 0; i < length; ++i) { StackValue coercedData = TypeSystem.Coerce(dataElements.GetValueAt(i), t, runtimeCore); oldValues[i] = SetValueForIndices(zippedIndices[i], coercedData, runtimeCore); } // The returned old values shouldn't have any key-value pairs try { return(heap.AllocateArray(oldValues)); } catch (RunOutOfMemoryException) { runtimeCore.RuntimeStatus.LogWarning(WarningID.RunOutOfMemory, Resources.RunOutOfMemory); return(StackValue.Null); } } else { // Replication is only on the LHS, so collect all old values // and return them in an array. StackValue coercedData = TypeSystem.Coerce(value, t, runtimeCore); StackValue[] oldValues = new StackValue[zippedIndices.Length]; for (int i = 0; i < zippedIndices.Length; ++i) { oldValues[i] = SetValueForIndices(zippedIndices[i], coercedData, runtimeCore); } // The returned old values shouldn't have any key-value pairs try { return(heap.AllocateArray(oldValues)); } catch (RunOutOfMemoryException) { runtimeCore.RuntimeStatus.LogWarning(WarningID.RunOutOfMemory, Resources.RunOutOfMemory); return(StackValue.Null); } } }
public static bool CompareFromDifferentCore(DSArray array1, DSArray array2, RuntimeCore rtCore1, RuntimeCore rtCore2, Context context = null) { if (array1.Count != array2.Count) { return false; } for (int i = 0; i < array1.Count; i++) { if (!StackUtils.CompareStackValues(array1.GetValueAt(i), array2.GetValueAt(i), rtCore1, rtCore2, context)) { return false; } } foreach (var key in array1.Dict.Keys) { StackValue value1 = array1.Dict[key]; StackValue value2 = StackValue.Null; if (!array2.Dict.TryGetValue(key, out value2)) { return false; } if (!StackUtils.CompareStackValues(value1, value2, rtCore1, rtCore2)) { return false; } } return true; }
//this method compares the values of the stack variables passed public static bool CompareStackValues(StackValue sv1, StackValue sv2, RuntimeCore rtCore1, RuntimeCore rtCore2, ProtoCore.Runtime.Context context = null) { if (sv1.optype != sv2.optype) { return(false); } switch (sv1.optype) { case AddressType.Invalid: return(true); case AddressType.Int: return(sv1.IntegerValue == sv2.IntegerValue); case AddressType.Char: return(sv1.CharValue == sv2.CharValue); case AddressType.Double: var value1 = sv1.DoubleValue; var value2 = sv2.DoubleValue; if (Double.IsInfinity(value1) && Double.IsInfinity(value2)) { return(true); } return(MathUtils.Equals(value1, value2)); case AddressType.Boolean: return(sv1.BooleanValue == sv2.BooleanValue); case AddressType.ArrayPointer: if (Object.ReferenceEquals(rtCore1, rtCore2) && sv1.ArrayPointer == sv2.ArrayPointer) //if both cores are same and the stack values point to the same heap element, then the stack values are equal { return(true); } DSArray array1 = rtCore1.Heap.ToHeapObject <DSArray>(sv1); DSArray array2 = rtCore2.Heap.ToHeapObject <DSArray>(sv2); return(DSArray.CompareFromDifferentCore(array1, array2, rtCore1, rtCore2, context)); case AddressType.String: if (Object.ReferenceEquals(rtCore1, rtCore2) && sv1.StringPointer == sv2.StringPointer) //if both cores are same and the stack values point to the same heap element, then the stack values are equal { return(true); } DSString s1 = rtCore1.Heap.ToHeapObject <DSString>(sv1); DSString s2 = rtCore1.Heap.ToHeapObject <DSString>(sv2); return(s1.Equals(s2)); case AddressType.Pointer: if (sv1.metaData.type != sv2.metaData.type) //if the type of class is different, then stack values can never be equal { return(false); } if (Object.ReferenceEquals(rtCore1, rtCore2) && sv1.Pointer == sv2.Pointer) //if both cores are same and the stack values point to the same heap element, then the stack values are equal { return(true); } ClassNode classnode = rtCore1.DSExecutable.classTable.ClassNodes[sv1.metaData.type]; if (classnode.IsImportedClass) { var helper = ProtoFFI.DLLFFIHandler.GetModuleHelper(ProtoFFI.FFILanguage.CSharp); var marshaller1 = helper.GetMarshaler(rtCore1); var marshaller2 = helper.GetMarshaler(rtCore2); try { //the interpreter is passed as null as it is not expected to be sued while unmarshalling in this scenario object dsObject1 = marshaller1.UnMarshal(sv1, context, null, typeof(Object)); object dsObject2 = marshaller2.UnMarshal(sv2, context, null, typeof(Object)); //cores are different in debugger nunit testing only. Most of the imported objects don't have implementation of Object.Equals. It //also does not make sense to compare these objects deeply, as only dummy objects are created in nunit testing, and these dummy objects //might have random values. So we just check whether the object tpye is the same for this testing. if (!object.ReferenceEquals(rtCore1, rtCore2)) { return(Object.ReferenceEquals(dsObject1.GetType(), dsObject2.GetType())); } return(Object.Equals(dsObject1, dsObject2)); } catch (System.Exception) { return(false); } } else { return(ComparePointerFromHeap(sv1, sv2, rtCore1, rtCore2, context)); } default: return(sv1.Equals(sv2)); } }