Sel *Ident;  // field selector
        };
 
-       // An IndexExpr node represents an expression followed by an index.
+       // An IndexExpr node represents an expression followed by an index or slice.
        IndexExpr struct {
                X Expr;  // expression
-               Index Expr;  // index expression
-       };
-
-       // A SliceExpr node represents an expression followed by a slice.
-       SliceExpr struct {
-               X Expr;  // expression
-               Begin, End Expr;  // slice range
+               Index Expr;  // index expression or beginning of slice range
+               End Expr;  // end of slice range; or nil
        };
 
        // A TypeAssertExpr node represents an expression followed by a
 // nodes.
 //
 type (
-       // An ArrayType node represents an array type.
+       // An ArrayType node represents an array or slice type.
        ArrayType struct {
                token.Position;  // position of "["
-               Len Expr;  // possibly an Ellipsis node for [...]T array types
-               Elt Expr;  // element type
-       };
-
-       // A SliceType node represents a slice type.
-       SliceType struct {
-               token.Position;  // position of "["
+               Len Expr;  // Ellipsis node for [...]T array types, nil for slice types
                Elt Expr;  // element type
        };
 
 func (x *CompositeLit) Pos() token.Position  { return x.Type.Pos(); }
 func (x *SelectorExpr) Pos() token.Position  { return x.X.Pos(); }
 func (x *IndexExpr) Pos() token.Position  { return x.X.Pos(); }
-func (x *SliceExpr) Pos() token.Position  { return x.X.Pos(); }
 func (x *TypeAssertExpr) Pos() token.Position  { return x.X.Pos(); }
 func (x *CallExpr) Pos() token.Position  { return x.Fun.Pos(); }
 func (x *BinaryExpr) Pos() token.Position  { return x.X.Pos(); }
        DoParenExpr(x *ParenExpr);
        DoSelectorExpr(x *SelectorExpr);
        DoIndexExpr(x *IndexExpr);
-       DoSliceExpr(x *SliceExpr);
        DoTypeAssertExpr(x *TypeAssertExpr);
        DoCallExpr(x *CallExpr);
        DoStarExpr(x *StarExpr);
        // Type expressions
        DoEllipsis(x *Ellipsis);
        DoArrayType(x *ArrayType);
-       DoSliceType(x *SliceType);
        DoStructType(x *StructType);
        DoFuncType(x *FuncType);
        DoInterfaceType(x *InterfaceType);
 func (x *ParenExpr) Visit(v ExprVisitor) { v.DoParenExpr(x); }
 func (x *SelectorExpr) Visit(v ExprVisitor) { v.DoSelectorExpr(x); }
 func (x *IndexExpr) Visit(v ExprVisitor) { v.DoIndexExpr(x); }
-func (x *SliceExpr) Visit(v ExprVisitor) { v.DoSliceExpr(x); }
 func (x *TypeAssertExpr) Visit(v ExprVisitor) { v.DoTypeAssertExpr(x); }
 func (x *CallExpr) Visit(v ExprVisitor) { v.DoCallExpr(x); }
 func (x *StarExpr) Visit(v ExprVisitor) { v.DoStarExpr(x); }
 func (x *KeyValueExpr) Visit(v ExprVisitor) { v.DoKeyValueExpr(x); }
 
 func (x *ArrayType) Visit(v ExprVisitor) { v.DoArrayType(x); }
-func (x *SliceType) Visit(v ExprVisitor) { v.DoSliceType(x); }
 func (x *StructType) Visit(v ExprVisitor) { v.DoStructType(x); }
 func (x *FuncType) Visit(v ExprVisitor) { v.DoFuncType(x); }
 func (x *InterfaceType) Visit(v ExprVisitor) { v.DoInterfaceType(x); }
 
 }
 
 
-func (p *parser) parseArrayOrSliceType(ellipsis_ok bool) ast.Expr {
+func (p *parser) parseArrayType(ellipsis_ok bool) ast.Expr {
        if p.trace {
-               defer un(trace(p, "ArrayOrSliceType"));
+               defer un(trace(p, "ArrayType"));
        }
 
        lbrack := p.expect(token.LBRACK);
        p.expect(token.RBRACK);
        elt := p.parseType();
 
-       if len != nil {
-               return &ast.ArrayType{lbrack, len, elt};
-       }
-
-       return &ast.SliceType{lbrack, elt};
+       return &ast.ArrayType{lbrack, len, elt};
 }
 
 
 func (p *parser) tryRawType(ellipsis_ok bool) ast.Expr {
        switch p.tok {
        case token.IDENT: return p.parseTypeName();
-       case token.LBRACK: return p.parseArrayOrSliceType(ellipsis_ok);
+       case token.LBRACK: return p.parseArrayType(ellipsis_ok);
        case token.STRUCT: return p.parseStructType();
        case token.MUL: return p.parsePointerType();
        case token.FUNC: return p.parseFuncType();
 }
 
 
-func (p *parser) parseIndexOrSlice(x ast.Expr) ast.Expr {
+func (p *parser) parseIndex(x ast.Expr) ast.Expr {
        if p.trace {
-               defer un(trace(p, "IndexOrSlice"));
+               defer un(trace(p, "Index"));
        }
 
        p.expect(token.LBRACK);
        p.expr_lev--;
        p.expect(token.RBRACK);
 
-       if end != nil {
-               return &ast.SliceExpr{x, begin, end};
-       }
-
-       return &ast.IndexExpr{x, begin};
+       return &ast.IndexExpr{x, begin, end};
 }
 
 
        case *ast.ParenExpr:
        case *ast.SelectorExpr:
        case *ast.IndexExpr:
-       case *ast.SliceExpr:
        case *ast.TypeAssertExpr:
        case *ast.CallExpr:
        case *ast.StarExpr:
        case *ast.ParenExpr: p.checkCompositeLitType(t.X);
        case *ast.SelectorExpr: p.checkTypeName(t.X);
        case *ast.ArrayType: return x;
-       case *ast.SliceType: return x;
        case *ast.StructType: return x;
        case *ast.MapType: return x;
        default:
        for {
                switch p.tok {
                case token.PERIOD: x = p.parseSelectorOrTypeAssertion(p.checkExpr(x));
-               case token.LBRACK: x = p.parseIndexOrSlice(p.checkExpr(x));
+               case token.LBRACK: x = p.parseIndex(p.checkExpr(x));
                case token.LPAREN: x = p.parseCallOrConversion(p.checkExprOrType(x));
                case token.LBRACE:
                        if p.expr_lev >= 0 {
 
 // Format file for printing AST nodes (package "ast").
 
 // ----------------------------------------------------------------------------
-// Debugging
+// Elementary types
 
 token.Token =
        ^:string;
 bytes =
        {*};
 
-nil =
-       ;  // TODO we see a lot of nil's - why?
+empty =
+       ;
 
 exists =
-       *:nil;
+       *:empty;
 
 
 // ----------------------------------------------------------------------------
        X "." Sel;
 
 ast.IndexExpr =
-       X "[" Index "]";
-
-ast.SliceExpr =
-       X "[" Begin ":" End "]";
+       X "[" Index [":" End] "]";
 
 ast.TypeAssertExpr =
        X ".(" Type ")";
        Key ": " Value;
 
 ast.ArrayType =
-       "[" Len "]" Elt;
-
-ast.SliceType =
-       "[]" Elt;
+       "[" [Len] "]" Elt;
 
 ast.StructType =
        "struct"
 
        P.Expr1(x.X, token.HighestPrec);
        P.Token(noPos, token.LBRACK);
        P.Expr(x.Index);
-       P.Token(noPos, token.RBRACK);
-}
-
-
-func (P *Printer) DoSliceExpr(x *ast.SliceExpr) {
-       P.Expr1(x.X, token.HighestPrec);
-       P.Token(noPos, token.LBRACK);
-       P.Expr(x.Begin);
-       P.Token(noPos, token.COLON);
-       P.Expr(x.End);
+       if x.End != nil {
+               P.Token(noPos, token.COLON);
+               P.Expr(x.End);
+       }
        P.Token(noPos, token.RBRACK);
 }
 
 
 func (P *Printer) DoArrayType(x *ast.ArrayType) {
        P.Token(x.Pos(), token.LBRACK);
-       P.Expr(x.Len);
-       P.Token(noPos, token.RBRACK);
-       P.Expr(x.Elt);
-}
-
-
-func (P *Printer) DoSliceType(x *ast.SliceType) {
-       P.Token(x.Pos(), token.LBRACK);
+       if x.Len != nil {
+               P.Expr(x.Len);
+       }
        P.Token(noPos, token.RBRACK);
        P.Expr(x.Elt);
 }