Support string concatenation with += operator
This commit is contained in:
parent
71a22509d7
commit
84c3f0f9bc
2 changed files with 32 additions and 3 deletions
|
@ -569,9 +569,32 @@ func (a *astBinder) checkBinaryOperatorExpression(node *ast.BinaryOperatorExpres
|
||||||
a.b.Diag().Errorf(errors.ErrorIllegalAssignmentTypes.At(node), rhs, lhs)
|
a.b.Diag().Errorf(errors.ErrorIllegalAssignmentTypes.At(node), rhs, lhs)
|
||||||
}
|
}
|
||||||
a.b.ctx.RegisterType(node, lhs)
|
a.b.ctx.RegisterType(node, lhs)
|
||||||
case ast.OpAssignSum, ast.OpAssignDifference, ast.OpAssignProduct, ast.OpAssignQuotient,
|
case ast.OpAssignSum:
|
||||||
|
// Lhs and rhs can be numbers (for addition) or strings (for concatenation).
|
||||||
|
if !a.isLValue(node.Left) {
|
||||||
|
a.b.Diag().Errorf(errors.ErrorIllegalAssignmentLValue.At(node))
|
||||||
|
a.b.ctx.RegisterType(node, types.Number)
|
||||||
|
} else if lhs == types.Number {
|
||||||
|
if rhs != types.Number {
|
||||||
|
a.b.Diag().Errorf(errors.ErrorBinaryOperatorInvalidForType.At(node),
|
||||||
|
node.Operator, "RHS", rhs, types.Number)
|
||||||
|
}
|
||||||
|
a.b.ctx.RegisterType(node, types.Number)
|
||||||
|
} else if lhs == types.String {
|
||||||
|
if rhs != types.String {
|
||||||
|
a.b.Diag().Errorf(errors.ErrorBinaryOperatorInvalidForType.At(node),
|
||||||
|
node.Operator, "RHS", rhs, types.String)
|
||||||
|
}
|
||||||
|
a.b.ctx.RegisterType(node, types.String)
|
||||||
|
} else {
|
||||||
|
a.b.Diag().Errorf(errors.ErrorBinaryOperatorInvalidForType.At(node),
|
||||||
|
node.Operator, "LHS", lhs, "string or number")
|
||||||
|
a.b.ctx.RegisterType(node, types.Number)
|
||||||
|
}
|
||||||
|
case ast.OpAssignDifference, ast.OpAssignProduct, ast.OpAssignQuotient,
|
||||||
ast.OpAssignRemainder, ast.OpAssignExponentiation, ast.OpAssignBitwiseShiftLeft, ast.OpAssignBitwiseShiftRight,
|
ast.OpAssignRemainder, ast.OpAssignExponentiation, ast.OpAssignBitwiseShiftLeft, ast.OpAssignBitwiseShiftRight,
|
||||||
ast.OpAssignBitwiseAnd, ast.OpAssignBitwiseOr, ast.OpAssignBitwiseXor:
|
ast.OpAssignBitwiseAnd, ast.OpAssignBitwiseOr, ast.OpAssignBitwiseXor:
|
||||||
|
// These operators require numeric values.
|
||||||
if !a.isLValue(node.Left) {
|
if !a.isLValue(node.Left) {
|
||||||
a.b.Diag().Errorf(errors.ErrorIllegalAssignmentLValue.At(node))
|
a.b.Diag().Errorf(errors.ErrorIllegalAssignmentLValue.At(node))
|
||||||
} else if lhs != types.Number {
|
} else if lhs != types.Number {
|
||||||
|
|
|
@ -1477,9 +1477,15 @@ func (e *evaluator) evalBinaryOperatorExpression(node *ast.BinaryOperatorExpress
|
||||||
e.evalAssign(node.Left, *lhsloc, rhs)
|
e.evalAssign(node.Left, *lhsloc, rhs)
|
||||||
return rhs, nil
|
return rhs, nil
|
||||||
case ast.OpAssignSum:
|
case ast.OpAssignSum:
|
||||||
// The target is a numeric l-value; just += rhs to it, and yield the new value as the result.
|
var val *rt.Object
|
||||||
ptr := lhs.PointerValue()
|
ptr := lhs.PointerValue()
|
||||||
val := e.alloc.NewNumber(ptr.Obj().NumberValue() + rhs.NumberValue())
|
if lhs.Type() == types.String {
|
||||||
|
// If the lhs/rhs are strings, just concatenate += and yield the new value as a result.
|
||||||
|
val = e.alloc.NewString(ptr.Obj().StringValue() + rhs.StringValue())
|
||||||
|
} else {
|
||||||
|
// Otherwise, the target is a numeric l-value; just += to it, and yield the new value as the result.
|
||||||
|
val = e.alloc.NewNumber(ptr.Obj().NumberValue() + rhs.NumberValue())
|
||||||
|
}
|
||||||
e.evalAssign(node.Left, *lhsloc, val)
|
e.evalAssign(node.Left, *lhsloc, val)
|
||||||
return val, nil
|
return val, nil
|
||||||
case ast.OpAssignDifference:
|
case ast.OpAssignDifference:
|
||||||
|
|
Loading…
Reference in a new issue