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.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.OpAssignBitwiseAnd, ast.OpAssignBitwiseOr, ast.OpAssignBitwiseXor:
|
||||
// These operators require numeric values.
|
||||
if !a.isLValue(node.Left) {
|
||||
a.b.Diag().Errorf(errors.ErrorIllegalAssignmentLValue.At(node))
|
||||
} else if lhs != types.Number {
|
||||
|
|
|
@ -1477,9 +1477,15 @@ func (e *evaluator) evalBinaryOperatorExpression(node *ast.BinaryOperatorExpress
|
|||
e.evalAssign(node.Left, *lhsloc, rhs)
|
||||
return rhs, nil
|
||||
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()
|
||||
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)
|
||||
return val, nil
|
||||
case ast.OpAssignDifference:
|
||||
|
|
Loading…
Reference in a new issue