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:
|
case *ast.SliceExpr:
|
||||||
var low, high Value
|
var low, high, max Value
|
||||||
var x Value
|
var x Value
|
||||||
switch fn.Pkg.typeOf(e.X).Underlying().(type) {
|
switch fn.Pkg.typeOf(e.X).Underlying().(type) {
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
|
@ -586,10 +586,14 @@ func (b *builder) expr0(fn *Function, e ast.Expr) Value {
|
||||||
if e.Low != nil {
|
if e.Low != nil {
|
||||||
low = b.expr(fn, e.Low)
|
low = b.expr(fn, e.Low)
|
||||||
}
|
}
|
||||||
|
if e.Slice3 {
|
||||||
|
max = b.expr(fn, e.Max)
|
||||||
|
}
|
||||||
v := &Slice{
|
v := &Slice{
|
||||||
X: x,
|
X: x,
|
||||||
Low: low,
|
Low: low,
|
||||||
High: high,
|
High: high,
|
||||||
|
Max: max,
|
||||||
}
|
}
|
||||||
v.setPos(e.Lbrack)
|
v.setPos(e.Lbrack)
|
||||||
v.setType(fn.Pkg.typeOf(e))
|
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]
|
fr.env[instr] = fr.get(instr.Tuple).(tuple)[instr.Index]
|
||||||
|
|
||||||
case *ssa.Slice:
|
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:
|
case *ssa.Return:
|
||||||
switch len(instr.Results) {
|
switch len(instr.Results) {
|
||||||
|
|
|
@ -231,29 +231,44 @@ func zero(t types.Type) value {
|
||||||
panic(fmt.Sprint("zero: unexpected ", t))
|
panic(fmt.Sprint("zero: unexpected ", t))
|
||||||
}
|
}
|
||||||
|
|
||||||
// slice returns x[lo:hi]. Either or both of lo and hi may be nil.
|
// slice returns x[lo:hi:max]. Any of lo, hi and max may be nil.
|
||||||
func slice(x, lo, hi value) value {
|
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
|
l := 0
|
||||||
if lo != nil {
|
if lo != nil {
|
||||||
l = asInt(lo)
|
l = asInt(lo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h := Len
|
||||||
|
if hi != nil {
|
||||||
|
h = asInt(hi)
|
||||||
|
}
|
||||||
|
|
||||||
|
m := Cap
|
||||||
|
if max != nil {
|
||||||
|
m = asInt(max)
|
||||||
|
}
|
||||||
|
|
||||||
switch x := x.(type) {
|
switch x := x.(type) {
|
||||||
case string:
|
case string:
|
||||||
if hi != nil {
|
return x[l:h]
|
||||||
return x[l:asInt(hi)]
|
|
||||||
}
|
|
||||||
return x[l:]
|
|
||||||
case []value:
|
case []value:
|
||||||
if hi != nil {
|
return x[l:h:m]
|
||||||
return x[l:asInt(hi)]
|
|
||||||
}
|
|
||||||
return x[l:]
|
|
||||||
case *value: // *array
|
case *value: // *array
|
||||||
a := (*x).(array)
|
a := (*x).(array)
|
||||||
if hi != nil {
|
return []value(a)[l:h:m]
|
||||||
return []value(a)[l:asInt(hi)]
|
|
||||||
}
|
|
||||||
return []value(a)[l:]
|
|
||||||
}
|
}
|
||||||
panic(fmt.Sprintf("slice: unexpected X type: %T", x))
|
panic(fmt.Sprintf("slice: unexpected X type: %T", x))
|
||||||
}
|
}
|
||||||
|
|
|
@ -624,3 +624,15 @@ func init() {
|
||||||
panic(r)
|
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 {
|
if v.High != nil {
|
||||||
b.WriteString(relName(v.High, v))
|
b.WriteString(relName(v.High, v))
|
||||||
}
|
}
|
||||||
|
if v.Max != nil {
|
||||||
|
b.WriteString(":")
|
||||||
|
b.WriteString(relName(v.Max, v))
|
||||||
|
}
|
||||||
b.WriteString("]")
|
b.WriteString("]")
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|
|
@ -723,8 +723,8 @@ type MakeSlice struct {
|
||||||
//
|
//
|
||||||
type Slice struct {
|
type Slice struct {
|
||||||
register
|
register
|
||||||
X Value // slice, string, or *array
|
X Value // slice, string, or *array
|
||||||
Low, High Value // either may be nil
|
Low, High, Max Value // each may be nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// The FieldAddr instruction yields the address of Field of *struct X.
|
// The FieldAddr instruction yields the address of Field of *struct X.
|
||||||
|
|
Loading…
Reference in New Issue