Index: src/Boo/Lang/RuntimeServices.cs
===================================================================
--- src/Boo/Lang/RuntimeServices.cs	(revision 1279)
+++ src/Boo/Lang/RuntimeServices.cs	(working copy)
@@ -270,7 +270,79 @@
 			Array.Copy(source, begin, target, 0, targetLen);
 			return target;
 		}
-		
+
+		public static Array GetMultiDimensionalRange1(Array source, params int[] ranges)
+		{
+			Array dest;
+			if (ranges.GetLength(0)/ 2 != source.Rank)
+				throw new Exception("invalid range passed: " + ranges.GetLength(0)/2 + ", expected " + source.Rank * 2);
+	
+			int[] newSize = new int[source.Rank];
+			for (int i = 0; i < source.Rank; i++)
+			{
+				ranges[(2*i)] = NormalizeIndex(source.GetLength(i), ranges[(2*i)]);
+				ranges[(2*i)+1] = NormalizeIndex(source.GetLength(i), ranges[(2*i)+1]);
+				newSize[i] = ranges[(2*i)+1] - ranges[2*i] + 1;
+			}
+	
+			dest = Array.CreateInstance(source.GetType().GetElementType(), newSize);
+			
+			CopyArrayEntries(source, dest, 0, ranges, null);
+			return dest;
+		}
+
+		private static void CopyArrayEntries (Array source, Array dest, int dimension, int[] ranges, int[] indices)
+		{       
+			if (dimension == source.Rank - 1)
+			{
+				int sourceStart = 0, destStart = 0;
+				int length = ranges[ranges.Length - 1] - ranges[ranges.Length - 2] + 1;
+				int unit = 1;
+	
+				unit = 1;
+				sourceStart += unit * ranges[ranges.Length - 2];
+				if (indices != null)
+				{
+					for (int i = 1; i < source.Rank; i++)
+					{
+						unit *= source.GetLength(source.Rank - i);
+						sourceStart += unit * indices[i-1];
+					}
+				}
+	
+				unit = 1;
+				if (indices != null)
+				{
+					for (int i = 1; i < dest.Rank; i++)
+					{
+						unit *= dest.GetLength(dest.Rank - i);
+						destStart += unit * (indices[i-1] - ranges[((ranges.Length/2 - i - 1) * 2)]);
+					}
+				}
+	
+	
+				Array.Copy(source, sourceStart, dest, destStart, length);
+			}
+			else
+			{       
+				int[] ind; // Array of indices to be passed to the recursive call
+	
+				if (indices != null)
+				{
+					ind = new int[indices.Length + 1];
+					Array.Copy(indices, 0, ind, 1, indices.Length);
+				} else {
+					ind = new int[1];
+				}
+	
+				for (int i = ranges[(dimension) * 2]; i <= ranges[(dimension) * 2 + 1]; i++)
+				{       
+					ind[0] = i;
+					CopyArrayEntries(source, dest, dimension + 1, ranges, ind);
+				}
+			}
+		}
+
 		public static void CheckArrayUnpack(Array array, int expected)
 		{
 			if (null == array)
Index: src/Boo/Lang/Builtins.cs
===================================================================
--- src/Boo/Lang/Builtins.cs	(revision 1279)
+++ 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 1279)
+++ 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 1279)
+++ 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 1279)
+++ 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 1279)
+++ 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 1279)
+++ src/Boo.Lang.Compiler/TypeSystem/TypeSystemServices.cs	(working copy)
@@ -635,15 +635,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 1279)
+++ 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 1279)
+++ 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 1279)
+++ src/Boo.Lang.Compiler/Steps/ProcessMethodBodies.cs	(working copy)
@@ -64,6 +64,8 @@
 		IMethod RuntimeServices_GetRange1;
 		
 		IMethod RuntimeServices_GetRange2;
+
+		IMethod RuntimeServices_GetMultiDimensionalRange1;
 		
 		IMethod RuntimeServices_GetEnumerable;
 		
@@ -92,11 +94,13 @@
 		IMethod Array_TypedCollectionConstructor;
 		
 		IMethod Array_TypedConstructor2;
+
+		IMethod MultiDimensionalArray_TypedConstructor;
 		
 		IMethod ICallable_Call;
 		
 		IMethod Activator_CreateInstance;
-		
+
 		IConstructor ApplicationException_StringConstructor;
 		
 		IConstructor TextReaderEnumerator_Constructor;
@@ -162,6 +166,7 @@
 			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_Len = ResolveMethod(TypeSystemServices.RuntimeServicesType, "Len");
 			RuntimeServices_Mid = ResolveMethod(TypeSystemServices.RuntimeServicesType, "Mid");
 			RuntimeServices_NormalizeStringIndex = ResolveMethod(TypeSystemServices.RuntimeServicesType, "NormalizeStringIndex");			
@@ -177,6 +182,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) }));
@@ -1431,8 +1437,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)
@@ -1447,6 +1461,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)
@@ -1503,23 +1529,53 @@
 		
 		void BindComplexArraySlicing(SlicingExpression node)
 		{			
-			Slice slice = node.Indices[0];
-			
-			if (CheckComplexSlicingParameters(slice))
+			if (CheckComplexSlicingParameters(node))
 			{
-				MethodInvocationExpression mie = null; 
-				
-				if (null == slice.End || slice.End == OmittedExpression.Default)
+				if (node.Indices.Count > 1)
 				{
-					mie = CodeBuilder.CreateMethodInvocation(RuntimeServices_GetRange1, node.Target, slice.Begin);
+					MethodInvocationExpression mie = null; 
+
+					ArrayLiteralExpression ranges = new ArrayLiteralExpression();
+					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)
+						{
+							ranges.Items.Add(node.Indices[i].Begin);
+						}
+						else
+						{
+						ranges.Items.Add(node.Indices[i].End);
+						}
+					}
+					mie = CodeBuilder.CreateMethodInvocation(RuntimeServices_GetMultiDimensionalRange1, node.Target, ranges);
+					
+					BindExpressionType(ranges, TypeSystemServices.Map(typeof(int[])));
+					BindExpressionType(mie, GetExpressionType(node.Target));
+					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);
+					}
+				}
 			}
 		}
 		
@@ -1594,13 +1650,7 @@
 				Error(node);
 				return;
 			}
-			
-			if (1 != node.Indices.Count)
-			{
-				NotImplemented(node, "multi dimensional slicing");
-				return;
-			}
-			
+
 			if (IsIndexedProperty(node.Target))
 			{
 				CheckNoComplexSlicing(node);
@@ -1611,19 +1661,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
@@ -1668,6 +1725,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))
@@ -1677,10 +1763,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 +3129,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]));
@@ -3407,32 +3503,62 @@
 		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)
 			{
+				if (!CheckTypeCompatibility(item.Begin, TypeSystemServices.IntType, GetExpressionType(item.Begin)))
+				{
+					Error(node);
+					return;
+				}
+			}
+
+			if (!CheckTypeCompatibility(node.Right, sliceTargetType.GetElementType(), lhsType))
+			{
 				Error(node);
 				return;
 			}
 			
-			node.ExpressionType = sliceTargetType.GetElementType();
+			if (slice.Indices.Count > 1)
+			{
+				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);
+			}
+			else
+			{
+				node.ExpressionType = sliceTargetType.GetElementType();
+			}
 		}
 		
 		void BindAssignmentToSliceProperty(BinaryExpression node)
 		{
 			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)
@@ -3445,21 +3571,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)
 			{		
@@ -3871,24 +3993,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 1279)
+++ src/Boo.Lang.Compiler/Steps/EmitAssembly.cs	(working copy)
@@ -2368,6 +2368,7 @@
 		void PushArguments(IMethod tag, ExpressionCollection args)
 		{
 			IParameter[] parameters = tag.GetParameters();
+		
 			for (int i=0; i<args.Count; ++i)
 			{
 				IType parameterType = parameters[i].Type;
@@ -2875,8 +2876,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
@@ -2925,8 +2932,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 1279)
+++ 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();
Index: src/Boo.AntlrParser/boo.g
===================================================================
--- src/Boo.AntlrParser/boo.g	(revision 1279)
+++ src/Boo.AntlrParser/boo.g	(working copy)
@@ -872,14 +872,18 @@
 	{
 		TypeReference tr = null;
 		atr = null;
+		IntegerLiteralExpression rank = null;
 	}:
 	lparen:LPAREN
-	tr=type_reference
-	rparen:RPAREN
 	{
 		atr = new ArrayTypeReference(ToLexicalInfo(lparen));
-		atr.ElementType = tr;
 	}
+	(
+		tr=type_reference { atr.ElementType = tr; }
+		(CARROT rank=integer_literal { atr.Rank = rank; })?
+	)
+	rparen:RPAREN
+
 	;
 
 protected
@@ -1912,12 +1916,55 @@
 	;
 	
 protected
-slicing_expression returns [Expression e]
+slice returns [Slice slice]
 	{
-		e = null;
+		slice = null;
 		Expression begin = null;
 		Expression end = null;
 		Expression step = null;		
+	} :
+	(
+		( 
+			// [:
+			COLON { begin = OmittedExpression.Default; }
+			(
+				// [:end]
+				end=expression
+				|
+				(
+					// [::step]
+					COLON { end = OmittedExpression.Default; }
+					step=expression
+				)
+				|
+				// [:]
+			)			
+		) |
+		// [begin
+		begin=expression
+		(
+			// [begin:
+			COLON
+			(
+				end=expression | { end = OmittedExpression.Default; } 
+			)
+			(
+				COLON
+				step=expression
+			)?
+		)?
+	)
+	{
+		slice = new Slice(begin, end, step);
+	}
+	;
+
+protected
+slicing_expression returns [Expression e]
+	{
+		e = null;
+		Slice item = null;
+		SlicingExpression se = null;
 		MethodInvocationExpression mce = null;
 		Token memberName = null;
 	} :
@@ -1927,43 +1974,22 @@
 			lbrack:LBRACK
 			(
 				( 
-					// [:
-					COLON { begin = OmittedExpression.Default; }
+					item=slice
 					(
-						// [:end]
-						end=expression
-						|
+						{
+							se = new SlicingExpression(ToLexicalInfo(lbrack));
+							se.Target = e;
+							se.Indices.Add(item);
+							e = se;
+						}
 						(
-							// [::step]
-							COLON { end = OmittedExpression.Default; }
-							step=expression
-						)
-						|
-						// [:]
-					)			
-				) |
-				// [begin
-				begin=expression
-				(
-					// [begin:
-					COLON
-					(
-						end=expression | { end = OmittedExpression.Default; } 
+							COMMA item=slice { se.Indices.Add(item); }
+						)*
 					)
-					(
-						COLON
-						step=expression
-					)?
-				)?
+				)
+				|
+				{ e = new SlicingExpression(ToLexicalInfo(lbrack)); }
 			)
-			{
-				SlicingExpression se = new SlicingExpression(ToLexicalInfo(lbrack));				
-				se.Target = e;
-				se.Indices.Add(new Slice(begin, end, step));
-				e = se;
-				
-				begin = end = step = null;
-			}
 			RBRACK
 		)
 		|
@@ -2396,6 +2422,8 @@
 
 COMMA : ',';
 
+CARROT : '^';
+
 protected
 TRIPLE_QUOTED_STRING:
 	"\"\""!
Index: tests/testcases/integration/arrays-32.boo
===================================================================
--- tests/testcases/integration/arrays-32.boo	(revision 0)
+++ tests/testcases/integration/arrays-32.boo	(revision 0)
@@ -0,0 +1,16 @@
+"""
+1
+2
+3
+4
+"""
+
+t = array(int, (2,2))
+
+t[0,0]=1
+t[0,1]=2
+t[1,0]=3
+t[1,1]=4
+
+for i in t:
+	print(i)
Index: tests/testcases/integration/arrays-33.boo
===================================================================
--- tests/testcases/integration/arrays-33.boo	(revision 0)
+++ tests/testcases/integration/arrays-33.boo	(revision 0)
@@ -0,0 +1,13 @@
+"""
+System.Int32[,]
+System.String[,]
+System.Object[,]
+"""
+
+t1 = array(int, (2,3))
+t2 = array(string, (3,3))
+t3 = array(object, (3,3))
+
+print (t1.GetType())
+print (t2.GetType())
+print (t3.GetType())
Index: tests/testcases/integration/arrays-29.boo
===================================================================
--- tests/testcases/integration/arrays-29.boo	(revision 0)
+++ tests/testcases/integration/arrays-29.boo	(revision 0)
@@ -0,0 +1,24 @@
+"""
+1
+0
+2
+0
+"""
+
+class Table:
+	_table = array(int, (2,2))
+
+	Item(x as int, y as int):
+		get:
+			return _table[x,y]
+		set:
+			_table[x,y] = value
+
+t = Table()
+t.Item[0,0]=1
+t.Item[1,0]=2
+
+print(t.Item[0,0])
+print(t.Item[0,1])
+print(t.Item[1,0])
+print(t.Item[1,1])
Index: tests/testcases/integration/arrays-30.boo
===================================================================
--- tests/testcases/integration/arrays-30.boo	(revision 0)
+++ tests/testcases/integration/arrays-30.boo	(revision 0)
@@ -0,0 +1,32 @@
+"""
+1
+2
+3
+4
+"""
+
+import System
+import System.Collections
+import System.Reflection
+
+
+[DefaultMember("Items")]
+class Col:
+	_objects = array(object, (2,2))
+
+	Items (x as int, y as int) as object:
+		get:
+			return _objects[x,y]
+		set:
+			_objects[x,y]=value
+
+col = Col()
+col[0,0] = 1
+col[0,1] = 2
+col[1,0] = 3
+col[1,1] = 4
+
+print(col[0,0])
+print(col[0,1])
+print(col[1,0])
+print(col[1,1])
Index: tests/testcases/integration/arrays-31.boo
===================================================================
--- tests/testcases/integration/arrays-31.boo	(revision 0)
+++ tests/testcases/integration/arrays-31.boo	(revision 0)
@@ -0,0 +1,14 @@
+"""
+3
+"""
+
+a = array(int,(3,3))
+
+a[0,0]=0
+a[0,1]=1
+a[0,2]=2
+a[1,0]=3
+a[2,0]=4
+a[3,0]=5
+
+print(a[1,-1])
Index: ast.model.boo
===================================================================
--- ast.model.boo	(revision 1279)
+++ ast.model.boo	(working copy)
@@ -43,6 +43,7 @@
 
 class ArrayTypeReference(TypeReference):
 	ElementType as TypeReference
+	Rank as IntegerLiteralExpression
 	
 class CallableTypeReference(TypeReference):
 	Parameters as TypeReferenceCollection

