Index: src/Boo/Lang/RuntimeServices.cs
===================================================================
--- src/Boo/Lang/RuntimeServices.cs	(revision 1317)
+++ src/Boo/Lang/RuntimeServices.cs	(working copy)
@@ -329,6 +329,159 @@
 			return target;
 		}
 
+	        public static void SetMultiDimensionalRange1 (Array source, Array dest, int[] ranges, bool[] collapse)
+	        {
+	                if (dest.Rank != ranges.Length / 2)
+			{
+	                        throw new Exception("invalid range passed: " + ranges.Length/2 + ", expected " + dest.Rank * 2);
+			}
+	
+			for (int i = 0; i < dest.Rank; i++)
+			{
+				if (ranges[2*i] > 0 ||
+					ranges[2*i] > dest.GetLength(i) ||
+					ranges[2*i+1] > dest.GetLength(i) ||
+					ranges[2*i+1] < ranges[2*i])
+				{
+					// FIXME: Better error reporting
+					Error("InvalidArray");
+				}
+			}
+
+			int sourceRank = 0;
+			foreach (bool val in collapse)
+			{
+				if (!val)
+				{
+					sourceRank++;
+				}
+			}
+
+			if (source.Rank != sourceRank)
+			{
+				// FIXME: Better error reporting
+				Error("InvalidArray");
+			}
+
+			int[] lensDest = new int[dest.Rank];
+			int[] lensSrc = new int[sourceRank];
+			int rankIndex = 0;
+			for (int i = 0; i < dest.Rank; i++)
+			{
+				lensDest[i]= ranges[2*i+1] - ranges[2*i];
+				if (!collapse[i])
+				{
+					lensSrc[rankIndex]= lensDest[i] - ranges[2*i];
+					if (lensSrc[rankIndex] != source.GetLength(rankIndex))
+					{
+						// FIXME: Better error reporting
+						Error("InvalidArray");
+					}
+					rankIndex++;
+				}
+			}
+
+			int[] modInd = new int[dest.Rank];
+			for (int i = 0; i < dest.Rank; i++)
+			{
+				if (i == 0)
+				{
+					modInd[i] = source.Length / lensDest[lensDest.Length - 1];
+				}
+				else
+				{
+					modInd[i] = modInd[i-1] / lensDest[i - 1];
+				}
+			}
+
+			int counter;
+			int[] indexDest = new int[dest.Rank];
+			int[] indexSrc = new int[sourceRank];
+			for (int i = 0; i < source.Length; i++)
+			{
+				counter = 0;
+				for (int j = 0; j < dest.Rank; j++)
+				{
+					int index = (i % modInd[j]) / (modInd[j] / lensDest[j]);
+					indexDest[j] = index;
+					if (!collapse[j])
+					{
+						indexSrc[counter] = indexDest[j] + ranges[2*j];
+						counter++;
+					}
+	                        	dest.SetValue(source.GetValue(indexSrc), indexDest);
+				}
+			}
+	        }
+
+		public static Array GetMultiDimensionalRange1(Array source, int[] ranges, bool[] collapse)
+		{
+			int rankSrc = source.Rank;
+			int collapseSize = 0;
+
+			foreach (bool val in collapse)
+			{
+				if (val)
+				{
+					collapseSize++;
+				}
+			}
+
+			int rankDest = rankSrc - collapseSize;
+			int[] lensDest = new int[rankDest];
+			int[] lensSrc = new int[rankSrc];
+	
+			int rankIndex = 0;
+			for (int i = 0; i < rankSrc; i++)
+			{
+				ranges[2*i] = NormalizeIndex(source.GetLength(i), ranges[2*i]);
+				ranges[2*i+1] = NormalizeIndex(source.GetLength(i), ranges[2*i+1]);
+
+				lensSrc[i]=ranges[2*i+1]-ranges[2*i];
+				if (!collapse[i])
+				{
+					lensDest[rankIndex]=ranges[2*i+1]-ranges[2*i];
+					rankIndex++;
+				}
+			}
+	
+			Array dest = Array.CreateInstance(source.GetType().GetElementType(), lensDest);
+
+			int[] modInd = new int[rankSrc];
+			int[] indicesDest = new int[rankDest];
+			int[] indicesSrc = new int[rankSrc];
+
+			for (int i = 0; i < rankSrc; i++)
+			{
+				if (i == 0)
+				{
+					modInd[i] = dest.Length;
+				}
+				else
+				{
+					modInd[i] = modInd[i-1] / lensSrc[i - 1];
+				}
+			}
+
+			for (int i = 0; i < dest.Length; i++)
+			{
+				int destIndex = 0;
+				for (int j = 0; j < rankSrc; j++)
+				{
+					int index = (i % modInd[j]) / (modInd[j] / lensSrc[j]);
+					indicesSrc[j]= ranges[2*j] + index;
+					if (!collapse[j])
+					{
+						indicesDest[destIndex]= indicesSrc[j] - ranges[2*j];
+						destIndex++;
+					}
+				}
+				dest.SetValue(source.GetValue(indicesSrc), indicesDest);
+			}
+	
+			return dest;
+		}
+
 		public static void CheckArrayUnpack(Array array, int expected)
 		{
 			if (null == array)
Index: src/Boo/Lang/Builtins.cs
===================================================================
--- src/Boo/Lang/Builtins.cs	(revision 1317)
+++ src/Boo/Lang/Builtins.cs	(working copy)
@@ -178,6 +178,15 @@
 			return Array.CreateInstance(elementType, length);
 		}
 
+		public static Array array(Type elementType, params int[] length)
+		{
+			if (null == elementType)
+			{
+				throw new ArgumentNullException("elementType");
+			}
+			return Array.CreateInstance(elementType, length);
+		}
+
 		public static IEnumerable iterator(object enumerable)
 		{
 			return RuntimeServices.GetEnumerable(enumerable);
Index: src/Boo/Resources/strings.txt
===================================================================
--- src/Boo/Resources/strings.txt	(revision 1317)
+++ src/Boo/Resources/strings.txt	(working copy)
@@ -107,6 +107,7 @@
 BCE0106=Failed to access the types defined in the assembly '{0}'.
 BCE0107=Value types cannot declare parameterless constructors.
 BCE0108=Value type fields cannot have initializers.
+BCE0109=Array '{0}' is rank '{1}', not rank '{2}'.
 
 ;Compiler warnings
 BCW0001=WARNING: Type '{0}' does not provide an implementation for '{1}' and will be marked abstract
Index: src/Boo.Lang.Compiler/TypeSystem/ArrayType.cs
===================================================================
--- src/Boo.Lang.Compiler/TypeSystem/ArrayType.cs	(revision 1317)
+++ src/Boo.Lang.Compiler/TypeSystem/ArrayType.cs	(working copy)
@@ -37,18 +37,34 @@
 		IType _elementType;
 		
 		IType _array;
+
+		int _rank;
 		
 		public ArrayType(TypeSystemServices tagManager, IType elementType)
 		{
 			_typeSystemServices = tagManager;
 			_array = tagManager.ArrayType;
 			_elementType = elementType;
+			_rank = 1;
 		}
+
+		public ArrayType(TypeSystemServices tagManager, IType elementType, int rank)
+		{
+			_typeSystemServices = tagManager;
+			_array = tagManager.ArrayType;
+			_elementType = elementType;
+			_rank = rank;
+		}
+
 		
 		public string Name
 		{
 			get
 			{
+				if (_rank > 1)
+				{
+					return "(" + _elementType.FullName + "^" + _rank + ")";
+				}
 				return "(" + _elementType.FullName + ")";
 			}
 		}
@@ -148,7 +164,7 @@
 		
 		public int GetArrayRank()
 		{
-			return 1;
+			return _rank;
 		}		
 		
 		public IType GetElementType()
@@ -183,7 +199,14 @@
 			
 			if (other.IsArray)
 			{
-				IType otherEntityType = ((IArrayType)other).GetElementType();
+				IArrayType otherArray = (IArrayType)other;
+
+				if (otherArray.GetArrayRank() != _rank)
+				{
+					return false;
+				}
+
+				IType otherEntityType = otherArray.GetElementType();
 				if (_elementType.IsValueType || otherEntityType.IsValueType)
 				{
 					return _elementType == otherEntityType;
Index: src/Boo.Lang.Compiler/TypeSystem/BooCodeBuilder.cs
===================================================================
--- src/Boo.Lang.Compiler/TypeSystem/BooCodeBuilder.cs	(revision 1317)
+++ src/Boo.Lang.Compiler/TypeSystem/BooCodeBuilder.cs	(working copy)
@@ -208,7 +208,10 @@
 			if (tag.IsArray)
 			{
 				IType elementType = ((IArrayType)tag).GetElementType();
-				typeReference = new ArrayTypeReference(CreateTypeReference(elementType));
+				typeReference = new ArrayTypeReference();
+				((ArrayTypeReference)typeReference).ElementType = CreateTypeReference(elementType);
+				// FIXME: This is what it *should* be, but it causes major breakage. ??
+				//typeReference = new ArrayTypeReference(CreateTypeReference(elementType), CreateIntegerLiteral(((IArrayType)tag).GetArrayRank()));
 			}
 			else
 			{				
Index: src/Boo.Lang.Compiler/TypeSystem/NameResolutionService.cs
===================================================================
--- src/Boo.Lang.Compiler/TypeSystem/NameResolutionService.cs	(revision 1317)
+++ src/Boo.Lang.Compiler/TypeSystem/NameResolutionService.cs	(working copy)
@@ -225,7 +225,14 @@
 			}
 			else
 			{
-				node.Entity = _context.TypeSystemServices.GetArrayType(elementType);
+				if (null == node.Rank)
+				{
+					node.Entity = _context.TypeSystemServices.GetArrayType(elementType);
+				}
+				else
+				{
+					node.Entity = _context.TypeSystemServices.GetArrayType(elementType, (int)node.Rank.Value);
+				}
 			}
 		}
 		
Index: src/Boo.Lang.Compiler/TypeSystem/TypeSystemServices.cs
===================================================================
--- src/Boo.Lang.Compiler/TypeSystem/TypeSystemServices.cs	(revision 1317)
+++ src/Boo.Lang.Compiler/TypeSystem/TypeSystemServices.cs	(working copy)
@@ -746,15 +725,49 @@
 		
 		public IArrayType GetArrayType(IType elementType)
 		{
-			IArrayType tag = (IArrayType)_arrayCache[elementType];
+			IArrayType tag = (IArrayType)_arrayCache[new ArrayHash(elementType,1)];
 			if (null == tag)
 			{
 				tag = new ArrayType(this, elementType);
-				_arrayCache.Add(elementType, tag);
+				_arrayCache.Add(new ArrayHash(elementType,1), tag);
 			}
 			return tag;
 		}
 		
+		public IArrayType GetArrayType(IType elementType, int rank)
+		{
+			IArrayType tag = (IArrayType)_arrayCache[new ArrayHash(elementType,rank)];
+			if (null == tag)
+			{
+				tag = new ArrayType(this, elementType, rank);
+				_arrayCache.Add(new ArrayHash(elementType,rank), tag);
+			}
+			return tag;
+		}
+
+		protected class ArrayHash {
+			
+			IType _type;
+
+			int _rank;
+
+			public ArrayHash(IType elementType, int rank)
+			{
+				_type = elementType;
+				_rank = rank;
+			}
+			
+			public override int GetHashCode()
+			{
+				return _type.GetHashCode() ^ _rank;
+			}
+
+			public override bool Equals(object obj)
+			{
+				return ((ArrayHash)obj)._type == _type && ((ArrayHash)obj)._rank == _rank;
+			}
+		}
+			
 		public IParameter[] Map(Boo.Lang.Compiler.Ast.ParameterDeclarationCollection parameters)
 		{
 			IParameter[] mapped = new IParameter[parameters.Count];
Index: src/Boo.Lang.Compiler/Ast/ArrayTypeReference.cs
===================================================================
--- src/Boo.Lang.Compiler/Ast/ArrayTypeReference.cs	(revision 1317)
+++ src/Boo.Lang.Compiler/Ast/ArrayTypeReference.cs	(working copy)
@@ -38,11 +38,11 @@
 		{
  		}
 		
-		public ArrayTypeReference(TypeReference elementType) : base(elementType)
+		public ArrayTypeReference(TypeReference elementType, IntegerLiteralExpression rank) : base(elementType, rank)
 		{
 		}
 		
-		public ArrayTypeReference(LexicalInfo lexicalInfo, TypeReference elementType) : base(lexicalInfo, elementType)
+		public ArrayTypeReference(LexicalInfo lexicalInfo, TypeReference elementType, IntegerLiteralExpression rank) : base(lexicalInfo, elementType, rank)
 		{
 		}
 		
Index: src/Boo.Lang.Compiler/Steps/IntroduceModuleClasses.cs
===================================================================
--- src/Boo.Lang.Compiler/Steps/IntroduceModuleClasses.cs	(revision 1317)
+++ src/Boo.Lang.Compiler/Steps/IntroduceModuleClasses.cs	(working copy)
@@ -104,7 +104,7 @@
 			if (node.Globals.Statements.Count > 0)
 			{
 				Method method = new Method(node.Globals.LexicalInfo);
-				method.Parameters.Add(new ParameterDeclaration("argv", new ArrayTypeReference(new SimpleTypeReference("string"))));
+				method.Parameters.Add(new ParameterDeclaration("argv", new ArrayTypeReference(new SimpleTypeReference("string"), new IntegerLiteralExpression(1))));
 				method.ReturnType = CodeBuilder.CreateTypeReference(TypeSystemServices.VoidType);
 				method.Body = node.Globals;
 				method.Name = EntryPointMethodName;
Index: src/Boo.Lang.Compiler/Steps/ProcessMethodBodies.cs
===================================================================
--- src/Boo.Lang.Compiler/Steps/ProcessMethodBodies.cs	(revision 1317)
+++ src/Boo.Lang.Compiler/Steps/ProcessMethodBodies.cs	(working copy)
@@ -64,7 +64,11 @@
 		IMethod RuntimeServices_GetRange1;
 		
 		IMethod RuntimeServices_GetRange2;
+
+		IMethod RuntimeServices_GetMultiDimensionalRange1;
 		
+		IMethod RuntimeServices_SetMultiDimensionalRange1;
+
 		IMethod RuntimeServices_GetEnumerable;
 		
 		IMethod RuntimeServices_op_Equality;
@@ -92,11 +96,13 @@
 		IMethod Array_TypedCollectionConstructor;
 		
 		IMethod Array_TypedConstructor2;
+
+		IMethod MultiDimensionalArray_TypedConstructor;
 		
 		IMethod ICallable_Call;
 		
 		IMethod Activator_CreateInstance;
-		
+
 		IConstructor ApplicationException_StringConstructor;
 		
 		IConstructor TextReaderEnumerator_Constructor;
@@ -162,6 +168,8 @@
 			RuntimeServices_AddArrays = ResolveMethod(TypeSystemServices.RuntimeServicesType, "AddArrays");
 			RuntimeServices_GetRange1 = ResolveMethod(TypeSystemServices.RuntimeServicesType, "GetRange1");
 			RuntimeServices_GetRange2 = ResolveMethod(TypeSystemServices.RuntimeServicesType, "GetRange2"); 			
+			RuntimeServices_GetMultiDimensionalRange1 = ResolveMethod(TypeSystemServices.RuntimeServicesType, "GetMultiDimensionalRange1"); 			
+			RuntimeServices_SetMultiDimensionalRange1 = ResolveMethod(TypeSystemServices.RuntimeServicesType, "SetMultiDimensionalRange1"); 			
 			RuntimeServices_Len = ResolveMethod(TypeSystemServices.RuntimeServicesType, "Len");
 			RuntimeServices_Mid = ResolveMethod(TypeSystemServices.RuntimeServicesType, "Mid");
 			RuntimeServices_NormalizeStringIndex = ResolveMethod(TypeSystemServices.RuntimeServicesType, "NormalizeStringIndex");			
@@ -177,6 +185,7 @@
 			Array_TypedEnumerableConstructor = (IMethod)TypeSystemServices.Map(Types.Builtins.GetMethod("array", new Type[] { Types.Type, Types.IEnumerable }));
 			Array_TypedCollectionConstructor= (IMethod)TypeSystemServices.Map(Types.Builtins.GetMethod("array", new Type[] { Types.Type, Types.ICollection }));
 			Array_TypedConstructor2 = (IMethod)TypeSystemServices.Map(Types.Builtins.GetMethod("array", new Type[] { Types.Type, Types.Int }));
+			MultiDimensionalArray_TypedConstructor = (IMethod)TypeSystemServices.Map(Types.Builtins.GetMethod("array", new Type[] { Types.Type, typeof(int[]) }));
 			ICallable_Call = ResolveMethod(TypeSystemServices.ICallableType, "Call");
 			Activator_CreateInstance = (IMethod)TypeSystemServices.Map(typeof(Activator).GetMethod("CreateInstance", new Type[] { Types.Type, Types.ObjectArray }));
 			TextReaderEnumerator_Constructor = (IConstructor)TypeSystemServices.Map(typeof(Boo.IO.TextReaderEnumerator).GetConstructor(new Type[] { typeof(System.IO.TextReader) }));
@@ -1432,8 +1441,16 @@
 		
 		bool IsComplexSlicing(SlicingExpression node)
 		{						
-			Slice slice = node.Indices[0];
-			return null != slice.End || null != slice.Step || OmittedExpression.Default == slice.Begin;
+			foreach (Slice slice in node.Indices)
+			{
+				if (null != slice.End ||
+				    null != slice.Step ||
+				    OmittedExpression.Default == slice.Begin)
+				{
+					return true;
+				}
+			}
+			return false;
 		}
 		
 		protected MethodInvocationExpression CreateEquals(BinaryExpression node)
@@ -1448,6 +1465,18 @@
 			return expression;
 		}
 		
+		bool CheckComplexSlicingParameters(SlicingExpression node)
+		{				
+			foreach (Slice slice in node.Indices)
+			{
+				if (!CheckComplexSlicingParameters(slice))
+				{
+					return false;
+				}
+			}
+			return true;
+		}
+
 		bool CheckComplexSlicingParameters(Slice node)
 		{				
 			if (null != node.Step)
@@ -1504,23 +1533,69 @@
 		
 		void BindComplexArraySlicing(SlicingExpression node)
 		{			
-			Slice slice = node.Indices[0];
-			
-			if (CheckComplexSlicingParameters(slice))
+			if (AstUtil.IsLhsOfAssignment(node))
 			{
-				MethodInvocationExpression mie = null; 
-				
-				if (null == slice.End || slice.End == OmittedExpression.Default)
+				return;
+			}
+
+			if (CheckComplexSlicingParameters(node))
+			{
+				if (node.Indices.Count > 1)
 				{
-					mie = CodeBuilder.CreateMethodInvocation(RuntimeServices_GetRange1, node.Target, slice.Begin);
+					IArrayType arrayType = (IArrayType)GetExpressionType(node.Target);
+					MethodInvocationExpression mie = null; 
+					ArrayLiteralExpression collapse = new ArrayLiteralExpression();
+					ArrayLiteralExpression ranges = new ArrayLiteralExpression();
+					int collapseCount = 0;
+					for (int i = 0; i < node.Indices.Count; i++)
+					{
+						ranges.Items.Add(node.Indices[i].Begin);
+						if (node.Indices[i].End == null ||
+							node.Indices[i].End == OmittedExpression.Default)
+						{
+							BinaryExpression end = new BinaryExpression(BinaryOperatorType.Addition,
+												node.Indices[i].Begin,
+												new IntegerLiteralExpression(1));
+							ranges.Items.Add(end);
+							BindExpressionType(end, GetExpressionType(node.Indices[i].Begin));
+							collapse.Items.Add(new BoolLiteralExpression(true));
+							collapseCount++;
+						}
+						else
+						{
+							ranges.Items.Add(node.Indices[i].End);
+							collapse.Items.Add(new BoolLiteralExpression(false));
+						}
+					}
+					mie = CodeBuilder.CreateMethodInvocation(RuntimeServices_GetMultiDimensionalRange1, node.Target, ranges);
+					mie.Arguments.Add(collapse);
+					
+					BindExpressionType(ranges, TypeSystemServices.Map(typeof(int[])));
+					BindExpressionType(collapse, TypeSystemServices.Map(typeof(bool[])));
+					BindExpressionType(mie, TypeSystemServices.GetArrayType(arrayType.GetElementType(), node.Indices.Count - collapseCount));
+					node.ParentNode.Replace(node, mie);
 				}
 				else
 				{
-					mie = CodeBuilder.CreateMethodInvocation(RuntimeServices_GetRange2, node.Target, slice.Begin, slice.End);
-				}				
-				
-				BindExpressionType(mie, GetExpressionType(node.Target));
-				node.ParentNode.Replace(node, mie);
+					Slice slice = node.Indices[0];
+					
+					if (CheckComplexSlicingParameters(slice))
+					{
+						MethodInvocationExpression mie = null; 
+						
+						if (null == slice.End || slice.End == OmittedExpression.Default)
+						{
+							mie = CodeBuilder.CreateMethodInvocation(RuntimeServices_GetRange1, node.Target, slice.Begin);
+						}
+						else
+						{
+							mie = CodeBuilder.CreateMethodInvocation(RuntimeServices_GetRange2, node.Target, slice.Begin, slice.End);
+						}				
+						
+						BindExpressionType(mie, GetExpressionType(node.Target));
+						node.ParentNode.Replace(node, mie);
+					}
+				}
 			}
 		}
 		
@@ -1595,13 +1670,7 @@
 				Error(node);
 				return;
 			}
-			
-			if (1 != node.Indices.Count)
-			{
-				NotImplemented(node, "multi dimensional slicing");
-				return;
-			}
-			
+
 			if (IsIndexedProperty(node.Target))
 			{
 				CheckNoComplexSlicing(node);
@@ -1612,19 +1681,26 @@
 				if (targetType.IsArray)
 				{
 					IArrayType arrayType = (IArrayType)targetType;
-					if (arrayType.GetArrayRank() != 1)
+					
+					if (arrayType.GetArrayRank() != node.Indices.Count)
 					{
-						Error(node, CompilerErrorFactory.InvalidArray(node.Target));
-						return;
+						Error(node, CompilerErrorFactory.InvalidArrayRank(node, node.Target.ToString(), arrayType.GetArrayRank(), node.Indices.Count));
 					}
-					
+
 					if (IsComplexSlicing(node))
 					{
 						BindComplexArraySlicing(node);
 					}
 					else
 					{
-						BindExpressionType(node, arrayType.GetElementType());
+						if (arrayType.GetArrayRank() > 1)
+						{
+							BindMultiDimensionalArraySlicing(node);
+						}
+						else
+						{
+							BindExpressionType(node, arrayType.GetElementType());
+						}
 					}
 				}
 				else
@@ -1669,6 +1745,35 @@
 				((IProperty)tag).GetParameters().Length > 0;
 		}
 		
+		void BindMultiDimensionalArraySlicing(SlicingExpression node)
+		{
+			if (AstUtil.IsLhsOfAssignment(node))
+			{
+				// leave it to LeaveBinaryExpression to resolve
+				return;
+			}
+
+			IArrayType arrayType = (IArrayType)GetExpressionType(node.Target);
+
+
+			ArrayLiteralExpression ale = new ArrayLiteralExpression();
+			MethodInvocationExpression mie = null;
+
+			for (int i = 0; i < node.Indices.Count; i++)
+			{
+				ale.Items.Add(node.Indices[i].Begin);
+			}
+
+			mie = CodeBuilder.CreateMethodInvocation(
+					node.Target,
+					(IMethod)TypeSystemServices.Map(typeof(Array).GetMethod("GetValue", new Type[] { typeof(int[]) })),
+					ale);
+			
+			BindExpressionType(ale, TypeSystemServices.Map(typeof(int[])));
+			BindExpressionType(mie, arrayType.GetElementType());
+			node.ParentNode.Replace(node, mie);
+		}
+
 		void SliceMember(SlicingExpression node, IEntity member, bool defaultMember)
 		{
 			if (AstUtil.IsLhsOfAssignment(node))
@@ -1678,10 +1783,12 @@
 				return;
 			}
 			
-			Slice index = node.Indices[0];
-			
 			MethodInvocationExpression mie = new MethodInvocationExpression(node.LexicalInfo);
-			mie.Arguments.Add(index.Begin);
+
+			foreach (Slice slice in node.Indices)
+			{
+				mie.Arguments.Add(slice.Begin);
+			}
 			
 			IMethod getter = null;
 			
@@ -3041,6 +3149,14 @@
 					inferredType = TypeSystemServices.GetArrayType(type);
 				}
 			}
+			else if (MultiDimensionalArray_TypedConstructor == method)
+			{
+				IType type = TypeSystemServices.GetReferencedType(expression.Arguments[0]);
+				if (null != type)
+				{				
+					inferredType = TypeSystemServices.GetArrayType(type, ((ArrayLiteralExpression)expression.Arguments[1]).Items.Count);
+				}
+			}
 			else if (Array_EnumerableConstructor == method)
 			{
 				IType enumeratorItemType = GetEnumeratorItemType(GetExpressionType(expression.Arguments[0]));
@@ -3408,39 +3524,130 @@
 			}
 			else
 			{
-				BindAssignmentToSliceProperty(node);
+				if (IsIndexedProperty(slice.Target))
+				{
+					BindAssignmentToSliceProperty(node, false);
+				}
+				else
+				{
+					BindAssignmentToSliceProperty(node, true);
+				}
 			}
 		}
 		
 		void BindAssignmentToSliceArray(BinaryExpression node)
 		{
 			SlicingExpression slice = (SlicingExpression)node.Left;
-			Slice index = slice.Indices[0];
 			
 			IArrayType sliceTargetType = (IArrayType)GetExpressionType(slice.Target);
 			IType lhsType = GetExpressionType(node.Right);
 			
-			if (!CheckTypeCompatibility(node.Right, sliceTargetType.GetElementType(), lhsType) ||
-				!CheckTypeCompatibility(index.Begin, TypeSystemServices.IntType, GetExpressionType(index.Begin)))
+			foreach (Slice item in slice.Indices)
 			{
-				Error(node);
-				return;
+				if (!CheckTypeCompatibility(item.Begin, TypeSystemServices.IntType, GetExpressionType(item.Begin)))
+				{
+					Error(node);
+					return;
+				}
 			}
-			
-			node.ExpressionType = sliceTargetType.GetElementType();
+
+			if (slice.Indices.Count > 1)
+			{
+				if (IsComplexSlicing(slice))
+				{
+					// FIXME: Check type compatibility
+					BindAssignmentToComplexSliceArray(node);
+				}
+				else
+				{
+				if (!CheckTypeCompatibility(node.Right, sliceTargetType.GetElementType(), lhsType))
+				{
+					Error(node);
+					return;
+				}
+					BindAssignmentToSimpleSliceArray(node);
+				}
+			}
+			else
+			{
+				if (!CheckTypeCompatibility(node.Right, sliceTargetType.GetElementType(), lhsType))
+				{
+					Error(node);
+					return;
+				}
+				node.ExpressionType = sliceTargetType.GetElementType();
+			}
 		}
+
+		void BindAssignmentToSimpleSliceArray(BinaryExpression node)
+		{
+			SlicingExpression slice = (SlicingExpression)node.Left;
+			ArrayLiteralExpression ale = new ArrayLiteralExpression();
+			for (int i = 0; i < slice.Indices.Count; i++)
+			{
+				ale.Items.Add(slice.Indices[i].Begin);
+			}
+								
+			MethodInvocationExpression mie = CodeBuilder.CreateMethodInvocation(
+								slice.Target,
+								(IMethod)TypeSystemServices.Map(typeof(Array).GetMethod("SetValue", new Type[] { typeof(object), typeof(int[]) })),
+								node.Right,
+								ale);
+								
+			BindExpressionType(mie, TypeSystemServices.VoidType);
+			BindExpressionType(ale, TypeSystemServices.Map(typeof(int[])));
+			node.ParentNode.Replace(node, mie);
+		}
+
+		void BindAssignmentToComplexSliceArray(BinaryExpression node)
+		{
+			SlicingExpression slice = (SlicingExpression)node.Left;
+			ArrayLiteralExpression ale = new ArrayLiteralExpression();
+			ArrayLiteralExpression collapse = new ArrayLiteralExpression();
+			for (int i = 0; i < slice.Indices.Count; i++)
+			{
+				ale.Items.Add(slice.Indices[i].Begin);
+				if (null == slice.Indices[i].End ||
+					OmittedExpression.Default == slice.Indices[i].End)
+				{
+					//ale.Items.Add(new BinaryExpression(BinaryOperatorType.Addition, slice.Indices[i].Begin, new IntegerLiteralExpression(1)));
+					ale.Items.Add(new IntegerLiteralExpression(1 + (int)((IntegerLiteralExpression)slice.Indices[i].Begin).Value));
+					collapse.Items.Add(new BoolLiteralExpression(true));
+				}
+				else
+				{
+					ale.Items.Add(slice.Indices[i].End);
+					collapse.Items.Add(new BoolLiteralExpression(false));
+				}
+			}
+								
+			MethodInvocationExpression mie = CodeBuilder.CreateMethodInvocation(
+								RuntimeServices_SetMultiDimensionalRange1,
+								node.Right,
+								slice.Target,
+								ale);
+								
+			mie.Arguments.Add(collapse);
+
+			BindExpressionType(mie, TypeSystemServices.VoidType);
+			BindExpressionType(ale, TypeSystemServices.Map(typeof(int[])));
+			BindExpressionType(collapse, TypeSystemServices.Map(typeof(bool[])));
+			node.ParentNode.Replace(node, mie);
+		}
 		
-		void BindAssignmentToSliceProperty(BinaryExpression node)
+		void BindAssignmentToSliceProperty(BinaryExpression node, bool defaultMember)
 		{
 			SlicingExpression slice = (SlicingExpression)node.Left;
-			Slice index = slice.Indices[0];
 			
 			IEntity lhs = GetEntity(node.Left);
 			IType rhs = GetExpressionType(node.Right);
 			IMethod setter = null;
 
 			MethodInvocationExpression mie = new MethodInvocationExpression(node.Left.LexicalInfo);
-			mie.Arguments.Add(index.Begin);
+			foreach (Slice item in slice.Indices)
+			{
+				mie.Arguments.Add(item.Begin);
+			}
 			mie.Arguments.Add(node.Right);			
 			
 			if (EntityType.Property == lhs.EntityType)
@@ -3453,21 +3660,17 @@
 				}
 				 
 				IParameter[] parameters = setMethod.GetParameters();
-				if (2 != parameters.Length)
+
+				for (int i = 0; i < slice.Indices.Count; i++)
 				{
-					Error(node, CompilerErrorFactory.MethodArgumentCount(node.Left, setMethod.FullName, 2));
-					return;
-				}
-				else
-				{
-					if (!CheckTypeCompatibility(index.Begin, parameters[0].Type, GetExpressionType(index.Begin)) ||
-						!CheckTypeCompatibility(node.Right, parameters[1].Type, rhs))
+					if (!CheckTypeCompatibility(slice.Indices[i].Begin, parameters[i].Type, GetExpressionType(slice.Indices[i].Begin)) ||
+						!CheckTypeCompatibility(node.Right, parameters[parameters.Length - 1].Type, rhs))
 					{					
 						Error(node);
 						return;
 					}
-					setter = setMethod;
 				}
+				setter = setMethod;
 			}
 			else if (EntityType.Ambiguous == lhs.EntityType)
 			{		
@@ -3480,7 +3683,13 @@
 			}
 			else
 			{	
-				mie.Target = CodeBuilder.CreateMemberReference(slice.Target, setter);
+				Expression target = slice.Target;
+				if (!defaultMember)
+				{
+					target = ((MemberReferenceExpression)slice.Target).Target;						
+				}
+
+				mie.Target = CodeBuilder.CreateMemberReference(target, setter);
 				BindExpressionType(mie, setter.ReturnType);	
 				node.ParentNode.Replace(node, mie);
 			}
@@ -3879,24 +4088,14 @@
 		void CheckIterator(Expression iterator, IType type, out bool runtimeIterator)
 		{	
 			runtimeIterator = false;
-			
-			if (type.IsArray)
-			{				
-				if (((IArrayType)type).GetArrayRank() != 1)
-				{
-					Error(CompilerErrorFactory.InvalidArray(iterator));
-				}
-			}
-			else
+			IType enumerable = TypeSystemServices.IEnumerableType;
+
+			if (!enumerable.IsAssignableFrom(type))
 			{
-				IType enumerable = TypeSystemServices.IEnumerableType;
-				if (!enumerable.IsAssignableFrom(type))
+				runtimeIterator = IsRuntimeIterator(type);
+				if (!runtimeIterator)
 				{
-					runtimeIterator = IsRuntimeIterator(type);
-					if (!runtimeIterator)
-					{
-						Error(CompilerErrorFactory.InvalidIteratorType(iterator, type.FullName));
-					}
+					Error(CompilerErrorFactory.InvalidIteratorType(iterator, type.FullName));
 				}
 			}
 		}		
Index: src/Boo.Lang.Compiler/Steps/EmitAssembly.cs
===================================================================
--- src/Boo.Lang.Compiler/Steps/EmitAssembly.cs	(revision 1317)
+++ src/Boo.Lang.Compiler/Steps/EmitAssembly.cs	(working copy)
@@ -425,6 +425,10 @@
 			EmitAttributes(builder, node);
 		}
 		
+		override public void OnArrayTypeReference(ArrayTypeReference node)
+		{
+		}
+
 		override public void OnClassDefinition(ClassDefinition node)
 		{
 			EmitTypeDefinition(node);
@@ -2908,8 +2912,14 @@
 						}
 						else
 						{
-							//type = Type.GetType(typeName, true);
-							type = Array.CreateInstance(GetSystemType(arrayType.GetElementType()), 0).GetType();
+							if (arrayType.GetArrayRank() > 1)
+							{
+								type = Array.CreateInstance(GetSystemType(arrayType.GetElementType()), new int[arrayType.GetArrayRank()]).GetType();
+							}
+							else
+							{
+								type = Array.CreateInstance(GetSystemType(arrayType.GetElementType()), 0).GetType();
+							}
 						}
 					}
 					else
@@ -2958,8 +2968,14 @@
 		{
 			if (tag.IsArray)
 			{
-				GetArrayTypeName(buffer, ((IArrayType)tag).GetElementType());
-				buffer.Append("[]");
+				IArrayType array = (IArrayType)tag;
+				GetArrayTypeName(buffer, array.GetElementType());
+				buffer.Append("[");
+				for (int i = 1; i < array.GetArrayRank(); i++)
+				{
+					buffer.Append(",");
+				}
+				buffer.Append("]");
 			}
 			else
 			{
Index: src/Boo.Lang.Compiler/CompilerErrorFactory.cs
===================================================================
--- src/Boo.Lang.Compiler/CompilerErrorFactory.cs	(revision 1317)
+++ src/Boo.Lang.Compiler/CompilerErrorFactory.cs	(working copy)
@@ -571,6 +571,11 @@
 			return new CompilerError("BCE0108", node.LexicalInfo);
 		}
 		
+		public static CompilerError InvalidArrayRank(Node node, string arrayName, int real, int given)
+		{
+			return new CompilerError("BCE0109", node.LexicalInfo, arrayName, real, given);
+		}
+		
 		public static string ToStringList(System.Collections.IEnumerable names)
 		{
 			StringBuilder builder = new StringBuilder();

