Preparation for simpler exprList use.
Change-Id: I2d62bbaba006aa3a378ec743564d46c5edcb8b47
Reviewed-on: https://go-review.googlesource.com/c/go/+/478016
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
switch len(elist) {
case 0:
// nothing to do
-
case 1:
- // single (possibly comma-ok) value, or function returning multiple values
- e := elist[0]
- var x operand
- check.multiExpr(&x, e)
- if t, ok := x.typ.(*Tuple); ok && x.mode != invalid {
- // multiple values
- xlist = make([]*operand, t.Len())
- for i, v := range t.vars {
- xlist[i] = &operand{mode: value, expr: e, typ: v.typ}
- }
- break
- }
-
- // exactly one (possibly invalid or comma-ok) value
- xlist = []*operand{&x}
- if allowCommaOk && (x.mode == mapindex || x.mode == commaok || x.mode == commaerr) {
- x2 := &operand{mode: value, expr: e, typ: Typ[UntypedBool]}
- if x.mode == commaerr {
- x2.typ = universeError
- }
- xlist = append(xlist, x2)
- commaOk = true
- }
-
+ return check.multiExpr(elist[0], allowCommaOk)
default:
// multiple (possibly invalid) values
xlist = make([]*operand, len(elist))
xlist[i] = &x
}
}
-
return
}
check.singleValue(x)
}
-// multiExpr is like expr but the result may also be a multi-value.
-func (check *Checker) multiExpr(x *operand, e syntax.Expr) {
- check.rawExpr(x, e, nil, false)
- check.exclude(x, 1<<novalue|1<<builtin|1<<typexpr)
+// multiExpr typechecks e and returns its value (or values) in list.
+// If allowCommaOk is set and e is a map index, comma-ok, or comma-err
+// expression, the result is a two-element list containing the value
+// of e, and an untyped bool value or an error value, respectively.
+func (check *Checker) multiExpr(e syntax.Expr, allowCommaOk bool) (list []*operand, commaOk bool) {
+ var x operand
+ check.rawExpr(&x, e, nil, false)
+ check.exclude(&x, 1<<novalue|1<<builtin|1<<typexpr)
+
+ if t, ok := x.typ.(*Tuple); ok && x.mode != invalid {
+ // multiple values
+ list = make([]*operand, t.Len())
+ for i, v := range t.vars {
+ list[i] = &operand{mode: value, expr: e, typ: v.typ}
+ }
+ return
+ }
+
+ // exactly one (possibly invalid or comma-ok) value
+ list = []*operand{&x}
+ if allowCommaOk && (x.mode == mapindex || x.mode == commaok || x.mode == commaerr) {
+ x2 := &operand{mode: value, expr: e, typ: Typ[UntypedBool]}
+ if x.mode == commaerr {
+ x2.typ = universeError
+ }
+ list = append(list, x2)
+ commaOk = true
+ }
+
+ return
}
// exprWithHint typechecks expression e and initializes x with the expression value;
switch len(elist) {
case 0:
// nothing to do
-
case 1:
- // single (possibly comma-ok) value, or function returning multiple values
- e := elist[0]
- var x operand
- check.multiExpr(&x, e)
- if t, ok := x.typ.(*Tuple); ok && x.mode != invalid {
- // multiple values
- xlist = make([]*operand, t.Len())
- for i, v := range t.vars {
- xlist[i] = &operand{mode: value, expr: e, typ: v.typ}
- }
- break
- }
-
- // exactly one (possibly invalid or comma-ok) value
- xlist = []*operand{&x}
- if allowCommaOk && (x.mode == mapindex || x.mode == commaok || x.mode == commaerr) {
- x2 := &operand{mode: value, expr: e, typ: Typ[UntypedBool]}
- if x.mode == commaerr {
- x2.typ = universeError
- }
- xlist = append(xlist, x2)
- commaOk = true
- }
-
+ return check.multiExpr(elist[0], allowCommaOk)
default:
// multiple (possibly invalid) values
xlist = make([]*operand, len(elist))
xlist[i] = &x
}
}
-
return
}
check.singleValue(x)
}
-// multiExpr is like expr but the result may also be a multi-value.
-func (check *Checker) multiExpr(x *operand, e ast.Expr) {
- check.rawExpr(x, e, nil, false)
- check.exclude(x, 1<<novalue|1<<builtin|1<<typexpr)
+// multiExpr typechecks e and returns its value (or values) in list.
+// If allowCommaOk is set and e is a map index, comma-ok, or comma-err
+// expression, the result is a two-element list containing the value
+// of e, and an untyped bool value or an error value, respectively.
+func (check *Checker) multiExpr(e ast.Expr, allowCommaOk bool) (list []*operand, commaOk bool) {
+ var x operand
+ check.rawExpr(&x, e, nil, false)
+ check.exclude(&x, 1<<novalue|1<<builtin|1<<typexpr)
+
+ if t, ok := x.typ.(*Tuple); ok && x.mode != invalid {
+ // multiple values
+ list = make([]*operand, t.Len())
+ for i, v := range t.vars {
+ list[i] = &operand{mode: value, expr: e, typ: v.typ}
+ }
+ return
+ }
+
+ // exactly one (possibly invalid or comma-ok) value
+ list = []*operand{&x}
+ if allowCommaOk && (x.mode == mapindex || x.mode == commaok || x.mode == commaerr) {
+ x2 := &operand{mode: value, expr: e, typ: Typ[UntypedBool]}
+ if x.mode == commaerr {
+ x2.typ = universeError
+ }
+ list = append(list, x2)
+ commaOk = true
+ }
+
+ return
}
// exprWithHint typechecks expression e and initializes x with the expression value;