public ObjectValue[] GetArrayChildren(ObjectCacheNode cacheNode,ObjectPath arrayPath, int index, int elementsToDisplay, EvaluationOptions options)
		{
			var t = cacheNode.NodeType as ArrayType;
			var elementType = t.ValueType;
			var sizeOfElement = SizeOf (elementType);

			ulong firstItemPointer;
			if (cacheNode is SubArrayCacheNode) {
				var sac = cacheNode as SubArrayCacheNode;
				firstItemPointer = sac.firstItem;
				elementsToDisplay = Math.Min (sac.length, index + elementsToDisplay) - index;
			} else {
				var header = Memory.ReadDArrayHeader (cacheNode.addressExpression);
				firstItemPointer = header.FirstItem.ToUInt64 ();
				elementsToDisplay = Math.Min (header.Length, index + elementsToDisplay) - index;
			}

			byte[] rawArrayContent;
			var startAddress = firstItemPointer + (ulong)(index * sizeOfElement);
			Memory.Read (startAddress.ToString (), sizeOfElement * elementsToDisplay, out rawArrayContent);

			var children = new ObjectValue[elementsToDisplay];
			ObjectPath item;

			var elementTypeToken = elementType is PrimitiveType ? (elementType as PrimitiveType).TypeToken : DTokens.INVALID;

			if (elementTypeToken != DTokens.INVALID)
			{
				var valFunc = DGdbTools.GetValueFunction (elementTypeToken);
				var elementTypeString = elementType.ToCode ();
				var hex = DisplayAsHex;

				for (uint i = 0; i < elementsToDisplay; i++) {
					var valStr = valFunc (rawArrayContent, (int)(i * sizeOfElement), hex);
					item = arrayPath.Append ((index + i).ToString ());

					children [i] = ObjectValue.CreatePrimitive (ValueSource, item, elementTypeString,
					                                            new EvaluationResult (valStr), ObjectValueFlags.ArrayElement);
				}
			}
			else if (elementType is ArrayType) {
				var elementArrayType = elementType as ArrayType;

				for (var i = elementsToDisplay - 1; i >= 0; i--){
					item = arrayPath.Append ((index + i).ToString ());
					try{
						int subArrayLength;
						ulong subArrayFirstPointer;
						ExamArrayInfo (rawArrayContent, i * sizeOfElement, out subArrayLength, out subArrayFirstPointer);

						children [i] = EvaluateArray (subArrayLength, subArrayFirstPointer, elementArrayType, 
						                              ObjectValueFlags.ArrayElement, item);
						cacheNode.Set(new SubArrayCacheNode(item.LastName, elementArrayType, subArrayFirstPointer, subArrayLength));

					}catch(Exception ex) {
						Ide.MessageService.ShowException (ex);
					}
									}
			}
			else if (elementType is PointerType || 
			         elementType is InterfaceType || 
			         elementType is ClassType) {

				for (int i = 0; i < elementsToDisplay; i++) {
					item = arrayPath.Append ((index + i).ToString ());

					long elementPointer;
					if (sizeOfElement == 4)
						elementPointer = BitConverter.ToInt32 (rawArrayContent, i * 4);
					else
						elementPointer = BitConverter.ToInt64 (rawArrayContent, i * 8);

					children [i] = EvaluateVariable (elementPointer.ToString (), ref elementType, ObjectValueFlags.ArrayElement, item);
					cacheNode.Set(new ObjectCacheNode(item.LastName, elementType, (elementPointer+i*sizeOfElement).ToString()));
				}
			}
			else if (elementType is StructType/* || elementType is UnionType*/) {
				// Get struct size or perhaps just get the struct meta information from gdb
				//return ObjectValue.CreateNotSupported (ValueSource, path, t.ToCode (), "Struct/Union arrays can't be examined yet", flags);
			} 

			return children;
		}
		public ObjectValue[] GetChildren (ObjectPath path, int firstItemIndex, int count, EvaluationOptions options)
		{
			EvaluationContext cctx = ctx.WithOptions (options);
			if (path.Length > 1) {
				// Looking for children of an array element
				int[] idx = StringToIndices (path [1]);
				object obj = array.GetElement (idx);
				return cctx.Adapter.GetObjectValueChildren (cctx, new ArrayObjectSource (array, path[1]), obj, firstItemIndex, count);
			}
			
			int lowerBound;
			int upperBound;
			bool isLastDimension;
			
			if (bounds.Length > 1) {
				int rank = baseIndices.Length;
				lowerBound = 0;
				upperBound = bounds [rank] - 1;
				isLastDimension = rank == bounds.Length - 1;
			} else {
				lowerBound = 0;
				upperBound = bounds [0] - 1;
				isLastDimension = true;
			}
			
			int len;
			int initalIndex;
			
			if (!IsRange) {
				initalIndex = lowerBound;
				len = upperBound + 1;
			}
			else {
				initalIndex = firstIndex;
				len = lastIndex - firstIndex + 1;
			}
			
			if (firstItemIndex == -1) {
				firstItemIndex = 0;
				count = len;
			}
			
			// Make sure the group doesn't have too many elements. If so, divide
			int div = 1;
			while (len / div > MaxChildCount)
				div *= 10;
			
			if (div == 1 && isLastDimension) {
				// Return array elements
				
				ObjectValue[] values = new ObjectValue [count];
				ObjectPath newPath = new ObjectPath ("this");
				
				int[] curIndex = new int [baseIndices.Length + 1];
				Array.Copy (baseIndices, curIndex, baseIndices.Length);
				string curIndexStr = IndicesToString (baseIndices);
				if (baseIndices.Length > 0) curIndexStr += ",";
				
				for (int n=0; n < values.Length; n++) {
					int index = n + initalIndex + firstItemIndex;
					string sidx = curIndexStr + index.ToString ();
					ObjectValue val;
					string ename = "[" + sidx.Replace (",",", ") + "]";
					if (index > upperBound)
						val = ObjectValue.CreateUnknown (sidx);
					else {
						curIndex [curIndex.Length - 1] = index;
						object elem = array.GetElement (curIndex);
						val = cctx.Adapter.CreateObjectValue (cctx, this, newPath.Append (sidx), elem, ObjectValueFlags.ArrayElement);
						if (elem != null && !cctx.Adapter.IsNull (cctx, elem)) {
							TypeDisplayData tdata = cctx.Adapter.GetTypeDisplayData (cctx, cctx.Adapter.GetValueType (cctx, elem));
							if (!string.IsNullOrEmpty (tdata.NameDisplayString))
								ename = cctx.Adapter.EvaluateDisplayString (cctx, elem, tdata.NameDisplayString);
						}
					}
					val.Name = ename;
					values [n] = val;
				}
				return values;
			}
			else if (!isLastDimension && div == 1) {
				// Return an array element group for each index
				
				List<ObjectValue> list = new List<ObjectValue> ();
				for (int i=0; i<count; i++) {
					int index = i + initalIndex + firstItemIndex;
					ObjectValue val;
					
					// This array must be created at every call to avoid sharing
					// changes with all array groups
					int[] curIndex = new int [baseIndices.Length + 1];
					Array.Copy (baseIndices, curIndex, baseIndices.Length);
					curIndex [curIndex.Length - 1] = index;
					
					if (index > upperBound)
						val = ObjectValue.CreateUnknown ("");
					else {
						ArrayElementGroup grp = new ArrayElementGroup (cctx, array, curIndex);
						val = grp.CreateObjectValue ();
					}
					list.Add (val);
				}
				return list.ToArray ();
			}
			else {
				// Too many elements. Split the array.
				
				// Don't make divisions of 10 elements, min is 100
				if (div == 10)
					div = 100;
				
				// Create the child groups
				int i = initalIndex + firstItemIndex;
				len += i;
				List<ObjectValue> list = new List<ObjectValue> ();
				while (i < len) {
					int end = i + div - 1;
					if (end > len)
						end = len - 1;
					ArrayElementGroup grp = new ArrayElementGroup (cctx, array, baseIndices, i, end);
					list.Add (grp.CreateObjectValue ());
					i += div;
				}
				return list.ToArray ();
			}
		}
		public ObjectValue[] GetClassInstanceChildren(ObjectCacheNode cacheNode,ObjectPath classPath, EvaluationOptions options)
		{
			bool isStruct = cacheNode.NodeType is StructType || cacheNode.NodeType is UnionType;

			if (!isStruct && !(cacheNode.NodeType is ClassType))
				throw new ArgumentException ("Can only handle structs, unions and classes!");

			var objectMembers = new List<ObjectValue> ();

			int objectSize;
			var members = GetMembersWithOffsets (cacheNode.NodeType as TemplateIntermediateType, out objectSize);

			// read in the object bytes -- The length of an object can be read dynamically and thus the primary range of bytes that contain object properties.
			byte[] bytes;

			if (isStruct) {
				Memory.Read (MemoryExamination.BuildAddressExpression(cacheNode.addressExpression, "&({0})"), objectSize, out bytes);
			}
			else
				bytes = Memory.ReadObjectBytes (cacheNode.addressExpression);

			foreach (var kv in members) {
				var member = kv.Item1;
				var currentOffset = kv.Item2;

				var memberType = member.Base;
				while (memberType is TemplateParameterSymbol || memberType is AliasedType)
					memberType = (memberType as DSymbol).Base;

				var memberFlags = BuildObjectValueFlags (member) | ObjectValueFlags.Field;
				var memberPath = classPath.Append (member.Name);

				try {
					if (memberType is PrimitiveType) {
						objectMembers.Add (EvaluatePrimitive (bytes, currentOffset, memberType as PrimitiveType, memberFlags, memberPath)); 

					} else if (memberType is ArrayType) {
						objectMembers.Add (EvaluateArray (bytes, currentOffset, memberType as ArrayType, memberFlags, memberPath));
					} 
					else if (memberType is PointerType ||
					         memberType is InterfaceType ||
					         memberType is ClassType) {
						long ptr;
						if (DGdbSession.Is64Bit)
							ptr = BitConverter.ToInt64 (bytes, currentOffset);
						else
							ptr = BitConverter.ToInt32 (bytes, currentOffset);

						if (ptr < 1)
							objectMembers.Add (ObjectValue.CreateNullObject (ValueSource, memberPath, memberType.ToCode(), memberFlags));
						else
							objectMembers.Add (EvaluateVariable (ptr.ToString (),ref memberType, memberFlags, memberPath));
					}
					else if(memberType is StructType)
						objectMembers.Add(ObjectValue.CreateObject(ValueSource, memberPath, memberType.ToCode(), memberType.ToString(), memberFlags, null));
				} catch (Exception ex) {
					Backtrace.DSession.LogWriter (false, "Error in GetClassInstanceChildren(memberPath="+memberPath.ToString()+"): " + ex.Message+"\n");
				}

				// TODO: use alignof property instead of constant

				// Create access expression for field inside the object.
				string addressExpression;
				if(isStruct)
				{
					addressExpression = MemoryExamination.EnforceReadRawExpression+"((void*)"+MemoryExamination.BuildAddressExpression(cacheNode.addressExpression, "&({0})")+ "+"+currentOffset+")";
				}
				else
					addressExpression = MemoryExamination.EnforceReadRawExpression+"((void*)"+MemoryExamination.BuildAddressExpression(cacheNode.addressExpression) + "+" + currentOffset+")";

				cacheNode.Set (new ObjectCacheNode (member.Name, memberType, addressExpression));
			}

			return objectMembers.ToArray ();
		}