go.tools/go/ssa: support 3-operand x[lo:hi:max] slices.
+ very basic test ($GOROOT/test/slice3.go needs unsafe.Pointer) LGTM=gri R=gri CC=golang-codereviews https://golang.org/cl/60030043
This commit is contained in:
parent
c37c5f6f46
commit
b3dbe56610
|
@ -569,7 +569,7 @@ func (b *builder) expr0(fn *Function, e ast.Expr) Value {
|
|||
}
|
||||
|
||||
case *ast.SliceExpr:
|
||||
var low, high Value
|
||||
var low, high, max Value
|
||||
var x Value
|
||||
switch fn.Pkg.typeOf(e.X).Underlying().(type) {
|
||||
case *types.Array:
|
||||
|
@ -586,10 +586,14 @@ func (b *builder) expr0(fn *Function, e ast.Expr) Value {
|
|||
if e.Low != nil {
|
||||
low = b.expr(fn, e.Low)
|
||||
}
|
||||
if e.Slice3 {
|
||||
max = b.expr(fn, e.Max)
|
||||
}
|
||||
v := &Slice{
|
||||
X: x,
|
||||
Low: low,
|
||||
High: high,
|
||||
Max: max,
|
||||
}
|
||||
v.setPos(e.Lbrack)
|
||||
v.setType(fn.Pkg.typeOf(e))
|
||||
|
|
|
@ -214,7 +214,7 @@ func visitInstr(fr *frame, instr ssa.Instruction) continuation {
|
|||
fr.env[instr] = fr.get(instr.Tuple).(tuple)[instr.Index]
|
||||
|
||||
case *ssa.Slice:
|
||||
fr.env[instr] = slice(fr.get(instr.X), fr.get(instr.Low), fr.get(instr.High))
|
||||
fr.env[instr] = slice(fr.get(instr.X), fr.get(instr.Low), fr.get(instr.High), fr.get(instr.Max))
|
||||
|
||||
case *ssa.Return:
|
||||
switch len(instr.Results) {
|
||||
|
|
|
@ -231,29 +231,44 @@ func zero(t types.Type) value {
|
|||
panic(fmt.Sprint("zero: unexpected ", t))
|
||||
}
|
||||
|
||||
// slice returns x[lo:hi]. Either or both of lo and hi may be nil.
|
||||
func slice(x, lo, hi value) value {
|
||||
// slice returns x[lo:hi:max]. Any of lo, hi and max may be nil.
|
||||
func slice(x, lo, hi, max value) value {
|
||||
var Len, Cap int
|
||||
switch x := x.(type) {
|
||||
case string:
|
||||
Len = len(x)
|
||||
case []value:
|
||||
Len = len(x)
|
||||
Cap = cap(x)
|
||||
case *value: // *array
|
||||
a := (*x).(array)
|
||||
Len = len(a)
|
||||
Cap = cap(a)
|
||||
}
|
||||
|
||||
l := 0
|
||||
if lo != nil {
|
||||
l = asInt(lo)
|
||||
}
|
||||
|
||||
h := Len
|
||||
if hi != nil {
|
||||
h = asInt(hi)
|
||||
}
|
||||
|
||||
m := Cap
|
||||
if max != nil {
|
||||
m = asInt(max)
|
||||
}
|
||||
|
||||
switch x := x.(type) {
|
||||
case string:
|
||||
if hi != nil {
|
||||
return x[l:asInt(hi)]
|
||||
}
|
||||
return x[l:]
|
||||
return x[l:h]
|
||||
case []value:
|
||||
if hi != nil {
|
||||
return x[l:asInt(hi)]
|
||||
}
|
||||
return x[l:]
|
||||
return x[l:h:m]
|
||||
case *value: // *array
|
||||
a := (*x).(array)
|
||||
if hi != nil {
|
||||
return []value(a)[l:asInt(hi)]
|
||||
}
|
||||
return []value(a)[l:]
|
||||
return []value(a)[l:h:m]
|
||||
}
|
||||
panic(fmt.Sprintf("slice: unexpected X type: %T", x))
|
||||
}
|
||||
|
|
|
@ -624,3 +624,15 @@ func init() {
|
|||
panic(r)
|
||||
}
|
||||
}
|
||||
|
||||
// Test of 3-operand x[lo:hi:max] slice.
|
||||
func init() {
|
||||
s := []int{0, 1, 2, 3}
|
||||
lenCapLoHi := func(x []int) [4]int { return [4]int{len(x), cap(x), x[0], x[len(x)-1]} }
|
||||
if got := lenCapLoHi(s[1:3]); got != [4]int{2, 3, 1, 2} {
|
||||
panic(got)
|
||||
}
|
||||
if got := lenCapLoHi(s[1:3:3]); got != [4]int{2, 2, 1, 2} {
|
||||
panic(got)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -201,6 +201,10 @@ func (v *Slice) String() string {
|
|||
if v.High != nil {
|
||||
b.WriteString(relName(v.High, v))
|
||||
}
|
||||
if v.Max != nil {
|
||||
b.WriteString(":")
|
||||
b.WriteString(relName(v.Max, v))
|
||||
}
|
||||
b.WriteString("]")
|
||||
return b.String()
|
||||
}
|
||||
|
|
|
@ -723,8 +723,8 @@ type MakeSlice struct {
|
|||
//
|
||||
type Slice struct {
|
||||
register
|
||||
X Value // slice, string, or *array
|
||||
Low, High Value // either may be nil
|
||||
X Value // slice, string, or *array
|
||||
Low, High, Max Value // each may be nil
|
||||
}
|
||||
|
||||
// The FieldAddr instruction yields the address of Field of *struct X.
|
||||
|
|
Loading…
Reference in New Issue