]> Cypherpunks repositories - gostls13.git/commitdiff
Permit omission of hi bound in slices.
authorRobert Griesemer <gri@golang.org>
Fri, 20 Nov 2009 00:42:05 +0000 (16:42 -0800)
committerRobert Griesemer <gri@golang.org>
Fri, 20 Nov 2009 00:42:05 +0000 (16:42 -0800)
R=r, rsc
https://golang.org/cl/157082

src/cmd/cgo/ast.go
src/pkg/exp/eval/expr.go
src/pkg/go/ast/ast.go
src/pkg/go/ast/walk.go
src/pkg/go/parser/parser.go
src/pkg/go/printer/nodes.go
src/pkg/go/printer/testdata/expressions.golden
src/pkg/go/printer/testdata/expressions.input
src/pkg/go/printer/testdata/expressions.raw

index f739c355aa1bf8e1b3fe4d43f709abd7ecbfa059..ccaef69d15050754cdf8f3798ce4a32bf7eea044 100644 (file)
@@ -178,6 +178,9 @@ func walk(x interface{}, p *Prog, context string) {
        case *ast.IndexExpr:
                walk(&n.X, p, "expr");
                walk(&n.Index, p, "expr");
+       case *ast.SliceExpr:
+               walk(&n.X, p, "expr");
+               walk(&n.Index, p, "expr");
                if n.End != nil {
                        walk(&n.End, p, "expr")
                }
index 265ba98d2bcc168392e0061b479d3db103a5a440..85f72b8106de802bbcf3926dd888b725257209b7 100644 (file)
@@ -581,21 +581,26 @@ func (a *exprCompiler) compile(x ast.Expr, callCtx bool) *expr {
                return ei.compileIdent(a.block, a.constant, callCtx, x.Value)
 
        case *ast.IndexExpr:
-               if x.End != nil {
-                       arr := a.compile(x.X, false);
-                       lo := a.compile(x.Index, false);
-                       hi := a.compile(x.End, false);
-                       if arr == nil || lo == nil || hi == nil {
-                               return nil
-                       }
-                       return ei.compileSliceExpr(arr, lo, hi);
-               }
                l, r := a.compile(x.X, false), a.compile(x.Index, false);
                if l == nil || r == nil {
                        return nil
                }
                return ei.compileIndexExpr(l, r);
 
+       case *ast.SliceExpr:
+               end := x.End;
+               if end == nil {
+                       // TODO: set end to len(x.X)
+                       panic("unimplemented")
+               }
+               arr := a.compile(x.X, false);
+               lo := a.compile(x.Index, false);
+               hi := a.compile(end, false);
+               if arr == nil || lo == nil || hi == nil {
+                       return nil
+               }
+               return ei.compileSliceExpr(arr, lo, hi);
+
        case *ast.KeyValueExpr:
                goto notimpl
 
index 1dfe2a7ea4085cd29744716a8e592bc4ce6c1a1a..60a90050c398718c9165426de770d0eaa974d3a5 100644 (file)
@@ -172,10 +172,16 @@ type (
                Sel     *Ident; // field selector
        };
 
-       // An IndexExpr node represents an expression followed by an index or slice.
+       // An IndexExpr node represents an expression followed by an index.
        IndexExpr       struct {
                X       Expr;   // expression
-               Index   Expr;   // index expression or beginning of slice range
+               Index   Expr;   // index expression
+       };
+
+       // An SliceExpr node represents an expression followed by slice indices.
+       SliceExpr       struct {
+               X       Expr;   // expression
+               Index   Expr;   // beginning of slice range
                End     Expr;   // end of slice range; or nil
        };
 
@@ -305,6 +311,7 @@ func (x *FuncLit) Pos() token.Position              { return x.Type.Pos() }
 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() }
@@ -323,6 +330,7 @@ func (x *CompositeLit) exprNode()   {}
 func (x *ParenExpr) exprNode()         {}
 func (x *SelectorExpr) exprNode()      {}
 func (x *IndexExpr) exprNode()         {}
+func (x *SliceExpr) exprNode()         {}
 func (x *TypeAssertExpr) exprNode()    {}
 func (x *CallExpr) exprNode()          {}
 func (x *StarExpr) exprNode()          {}
index c1ed3662157f9c918ee288495c522c379ce17f80..08c3992192c0784504fb0e660cfcd4f20b454f7f 100644 (file)
@@ -129,6 +129,10 @@ func Walk(v Visitor, node interface{}) {
        case *IndexExpr:
                Walk(v, n.X);
                Walk(v, n.Index);
+
+       case *SliceExpr:
+               Walk(v, n.X);
+               Walk(v, n.Index);
                Walk(v, n.End);
 
        case *TypeAssertExpr:
index ba91ceb52b1ad19525610a92df8787561a6dd8a9..1195a24fa6dbf6c00d09c4d2ca24928d21a9bde3 100644 (file)
@@ -962,23 +962,28 @@ func (p *parser) parseSelectorOrTypeAssertion(x ast.Expr) ast.Expr {
 }
 
 
-func (p *parser) parseIndex(x ast.Expr) ast.Expr {
+func (p *parser) parseIndexOrSlice(x ast.Expr) ast.Expr {
        if p.trace {
-               defer un(trace(p, "Index"))
+               defer un(trace(p, "IndexOrSlice"))
        }
 
        p.expect(token.LBRACK);
        p.exprLev++;
-       begin := p.parseExpr();
-       var end ast.Expr;
+       index := p.parseExpr();
        if p.tok == token.COLON {
                p.next();
-               end = p.parseExpr();
+               var end ast.Expr;
+               if p.tok != token.RBRACK {
+                       end = p.parseExpr()
+               }
+               x = &ast.SliceExpr{x, index, end};
+       } else {
+               x = &ast.IndexExpr{x, index}
        }
        p.exprLev--;
        p.expect(token.RBRACK);
 
-       return &ast.IndexExpr{x, begin, end};
+       return x;
 }
 
 
@@ -1072,6 +1077,7 @@ func (p *parser) checkExpr(x ast.Expr) ast.Expr {
        case *ast.ParenExpr:
        case *ast.SelectorExpr:
        case *ast.IndexExpr:
+       case *ast.SliceExpr:
        case *ast.TypeAssertExpr:
                if t.Type == nil {
                        // the form X.(type) is only allowed in type switch expressions
@@ -1168,7 +1174,7 @@ L:        for {
                case token.PERIOD:
                        x = p.parseSelectorOrTypeAssertion(p.checkExpr(x))
                case token.LBRACK:
-                       x = p.parseIndex(p.checkExpr(x))
+                       x = p.parseIndexOrSlice(p.checkExpr(x))
                case token.LPAREN:
                        x = p.parseCallOrConversion(p.checkExprOrType(x))
                case token.LBRACE:
index 243c168a7fca339531c6aa9476e2375edd55b99e..6304830bd35811946931098074ed7d9ff9dff9fe 100644 (file)
@@ -665,17 +665,25 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, ctxt exprContext, multi
                p.print(token.RPAREN);
 
        case *ast.IndexExpr:
+               // TODO(gri): should treat[] like parentheses and undo one level of depth
                p.expr1(x.X, token.HighestPrec, 1, 0, multiLine);
                p.print(token.LBRACK);
                p.expr0(x.Index, depth+1, multiLine);
+               p.print(token.RBRACK);
+
+       case *ast.SliceExpr:
+               // TODO(gri): should treat[] like parentheses and undo one level of depth
+               p.expr1(x.X, token.HighestPrec, 1, 0, multiLine);
+               p.print(token.LBRACK);
+               p.expr0(x.Index, depth+1, multiLine);
+               // blanks around ":" if both sides exist and either side is a binary expression
+               if depth <= 1 && x.End != nil && (isBinary(x.Index) || isBinary(x.End)) {
+                       p.print(blank, token.COLON, blank)
+               } else {
+                       p.print(token.COLON)
+               }
                if x.End != nil {
-                       // blanks around ":" if either side is a binary expression
-                       if depth <= 1 && (isBinary(x.Index) || isBinary(x.End)) {
-                               p.print(blank, token.COLON, blank)
-                       } else {
-                               p.print(token.COLON)
-                       }
-                       p.expr0(x.End, depth+1, multiLine);
+                       p.expr0(x.End, depth+1, multiLine)
                }
                p.print(token.RBRACK);
 
index 1d785d91f3981209a46e23c3ac99e6303e433dfd..0530e81da7efa18b1e5b0d25d61300d8f6efef79 100644 (file)
@@ -53,6 +53,11 @@ func _() {
        _ = 1 + 2*3;
        _ = s[1 : 2*3];
        _ = s[a : b-c];
+       _ = s[0:];
+       _ = s[a+b];
+       _ = s[a+b:];
+       _ = a[a<<b+1];
+       _ = a[a<<b+1:];
        _ = s[a+b : len(s)];
        _ = s[len(s):-a];
        _ = s[a : len(s)+1];
index 6ccc9a83358a68cbb221b442512afd1b4619ced2..decb58196dd37f32ce3486b9a5fd39a721d67a04 100644 (file)
@@ -53,6 +53,11 @@ func _() {
        _ = 1 + 2*3;
        _ = s[1 : 2*3];
        _ = s[a : b-c];
+       _ = s[0:];
+       _ = s[a+b];
+       _ = s[a+b :];
+       _ = a[a<<b+1];
+       _ = a[a<<b+1 :];
        _ = s[a+b : len(s)];
        _ = s[len(s) : -a];
        _ = s[a : len(s)+1];
index 55986e2e628aa451dabd7225a65d7be25431d9c8..3e4f3264882101dfd88431d776de3898b976d321 100644 (file)
@@ -53,6 +53,11 @@ func _() {
        _ = 1 + 2*3;
        _ = s[1 : 2*3];
        _ = s[a : b-c];
+       _ = s[0:];
+       _ = s[a+b];
+       _ = s[a+b:];
+       _ = a[a<<b+1];
+       _ = a[a<<b+1:];
        _ = s[a+b : len(s)];
        _ = s[len(s):-a];
        _ = s[a : len(s)+1];