mirror of
https://github.com/golang/go.git
synced 2024-09-21 18:38:37 +00:00
[dev.unified] cmd/compile: refactor range
desugaring
This CL refactors the code responsible for emitting the user-visible assignments within a range statement. This will make it easier to propagate RTTI from the frontend into any implicit conversions. Updates #53328. Change-Id: Ibed15e3b4951b0a6a726067b401a630977f4c6c2 Reviewed-on: https://go-review.googlesource.com/c/go/+/415158 Reviewed-by: David Chase <drchase@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
3635b07d16
commit
0a503cf43a
@ -103,7 +103,7 @@ func walkRange(nrange *ir.RangeStmt) ir.Node {
|
|||||||
|
|
||||||
// for v1 := range ha { body }
|
// for v1 := range ha { body }
|
||||||
if v2 == nil {
|
if v2 == nil {
|
||||||
body = []ir.Node{ir.NewAssignStmt(base.Pos, v1, hv1)}
|
body = []ir.Node{rangeAssign(nrange, hv1)}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,10 +112,7 @@ func walkRange(nrange *ir.RangeStmt) ir.Node {
|
|||||||
// v1, v2 = hv1, ha[hv1]
|
// v1, v2 = hv1, ha[hv1]
|
||||||
tmp := ir.NewIndexExpr(base.Pos, ha, hv1)
|
tmp := ir.NewIndexExpr(base.Pos, ha, hv1)
|
||||||
tmp.SetBounded(true)
|
tmp.SetBounded(true)
|
||||||
// Use OAS2 to correctly handle assignments
|
body = []ir.Node{rangeAssign2(nrange, hv1, tmp)}
|
||||||
// of the form "v1, a[v1] := range".
|
|
||||||
a := ir.NewAssignListStmt(base.Pos, ir.OAS2, []ir.Node{v1, v2}, []ir.Node{hv1, tmp})
|
|
||||||
body = []ir.Node{a}
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,9 +137,7 @@ func walkRange(nrange *ir.RangeStmt) ir.Node {
|
|||||||
tmp.SetBounded(true)
|
tmp.SetBounded(true)
|
||||||
init = append(init, ir.NewAssignStmt(base.Pos, hp, typecheck.NodAddr(tmp)))
|
init = append(init, ir.NewAssignStmt(base.Pos, hp, typecheck.NodAddr(tmp)))
|
||||||
|
|
||||||
// Use OAS2 to correctly handle assignments
|
a := rangeAssign2(nrange, hv1, ir.NewStarExpr(base.Pos, hp))
|
||||||
// of the form "v1, a[v1] := range".
|
|
||||||
a := ir.NewAssignListStmt(base.Pos, ir.OAS2, []ir.Node{v1, v2}, []ir.Node{hv1, ir.NewStarExpr(base.Pos, hp)})
|
|
||||||
body = append(body, a)
|
body = append(body, a)
|
||||||
|
|
||||||
// Advance pointer as part of the late increment.
|
// Advance pointer as part of the late increment.
|
||||||
@ -179,11 +174,10 @@ func walkRange(nrange *ir.RangeStmt) ir.Node {
|
|||||||
if v1 == nil {
|
if v1 == nil {
|
||||||
body = nil
|
body = nil
|
||||||
} else if v2 == nil {
|
} else if v2 == nil {
|
||||||
body = []ir.Node{ir.NewAssignStmt(base.Pos, v1, key)}
|
body = []ir.Node{rangeAssign(nrange, key)}
|
||||||
} else {
|
} else {
|
||||||
elem := ir.NewStarExpr(base.Pos, ir.NewSelectorExpr(base.Pos, ir.ODOT, hit, elemsym))
|
elem := ir.NewStarExpr(base.Pos, ir.NewSelectorExpr(base.Pos, ir.ODOT, hit, elemsym))
|
||||||
a := ir.NewAssignListStmt(base.Pos, ir.OAS2, []ir.Node{v1, v2}, []ir.Node{key, elem})
|
body = []ir.Node{rangeAssign2(nrange, key, elem)}
|
||||||
body = []ir.Node{a}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case types.TCHAN:
|
case types.TCHAN:
|
||||||
@ -206,7 +200,7 @@ func walkRange(nrange *ir.RangeStmt) ir.Node {
|
|||||||
if v1 == nil {
|
if v1 == nil {
|
||||||
body = nil
|
body = nil
|
||||||
} else {
|
} else {
|
||||||
body = []ir.Node{ir.NewAssignStmt(base.Pos, v1, hv1)}
|
body = []ir.Node{rangeAssign(nrange, hv1)}
|
||||||
}
|
}
|
||||||
// Zero hv1. This prevents hv1 from being the sole, inaccessible
|
// Zero hv1. This prevents hv1 from being the sole, inaccessible
|
||||||
// reference to an otherwise GC-able value during the next channel receive.
|
// reference to an otherwise GC-able value during the next channel receive.
|
||||||
@ -271,11 +265,10 @@ func walkRange(nrange *ir.RangeStmt) ir.Node {
|
|||||||
if v1 != nil {
|
if v1 != nil {
|
||||||
if v2 != nil {
|
if v2 != nil {
|
||||||
// v1, v2 = hv1t, hv2
|
// v1, v2 = hv1t, hv2
|
||||||
a := ir.NewAssignListStmt(base.Pos, ir.OAS2, []ir.Node{v1, v2}, []ir.Node{hv1t, hv2})
|
body = append(body, rangeAssign2(nrange, hv1t, hv2))
|
||||||
body = append(body, a)
|
|
||||||
} else {
|
} else {
|
||||||
// v1 = hv1t
|
// v1 = hv1t
|
||||||
body = append(body, ir.NewAssignStmt(base.Pos, v1, hv1t))
|
body = append(body, rangeAssign(nrange, hv1t))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -310,6 +303,20 @@ func walkRange(nrange *ir.RangeStmt) ir.Node {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rangeAssign returns "n.Key = key".
|
||||||
|
func rangeAssign(n *ir.RangeStmt, key ir.Node) ir.Node {
|
||||||
|
// TODO(mdempsky): Implicit conversions for test/typeparam/mdempsky/17.go.
|
||||||
|
return ir.NewAssignStmt(n.Pos(), n.Key, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// rangeAssign2 returns "n.Key, n.Value = key, value".
|
||||||
|
func rangeAssign2(n *ir.RangeStmt, key, value ir.Node) ir.Node {
|
||||||
|
// Use OAS2 to correctly handle assignments
|
||||||
|
// of the form "v1, a[v1] = range".
|
||||||
|
// TODO(mdempsky): Implicit conversions for test/typeparam/mdempsky/17.go.
|
||||||
|
return ir.NewAssignListStmt(n.Pos(), ir.OAS2, []ir.Node{n.Key, n.Value}, []ir.Node{key, value})
|
||||||
|
}
|
||||||
|
|
||||||
// isMapClear checks if n is of the form:
|
// isMapClear checks if n is of the form:
|
||||||
//
|
//
|
||||||
// for k := range m {
|
// for k := range m {
|
||||||
|
Loading…
Reference in New Issue
Block a user