2025-10-15 10:12:44 +03:00

114 lines
3.3 KiB
Go

package estransforms
import (
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/ast"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/transformers"
)
type logicalAssignmentTransformer struct {
transformers.Transformer
}
func (ch *logicalAssignmentTransformer) visit(node *ast.Node) *ast.Node {
if node.SubtreeFacts()&ast.SubtreeContainsLogicalAssignments == 0 {
return node
}
switch node.Kind {
case ast.KindBinaryExpression:
return ch.visitBinaryExpression(node.AsBinaryExpression())
default:
return ch.Visitor().VisitEachChild(node)
}
}
func (ch *logicalAssignmentTransformer) visitBinaryExpression(node *ast.BinaryExpression) *ast.Node {
var nonAssignmentOperator ast.Kind
switch node.OperatorToken.Kind {
case ast.KindBarBarEqualsToken:
nonAssignmentOperator = ast.KindBarBarToken
case ast.KindAmpersandAmpersandEqualsToken:
nonAssignmentOperator = ast.KindAmpersandAmpersandToken
case ast.KindQuestionQuestionEqualsToken:
nonAssignmentOperator = ast.KindQuestionQuestionToken
default:
return ch.Visitor().VisitEachChild(node.AsNode())
}
left := ast.SkipParentheses(ch.Visitor().VisitNode(node.Left))
assignmentTarget := left
right := ast.SkipParentheses(ch.Visitor().VisitNode(node.Right))
if ast.IsAccessExpression(left) {
propertyAccessTargetSimpleCopiable := transformers.IsSimpleCopiableExpression(left.Expression())
propertyAccessTarget := left.Expression()
propertyAccessTargetAssignment := left.Expression()
if !propertyAccessTargetSimpleCopiable {
propertyAccessTarget = ch.Factory().NewTempVariable()
ch.EmitContext().AddVariableDeclaration(propertyAccessTarget)
propertyAccessTargetAssignment = ch.Factory().NewAssignmentExpression(
propertyAccessTarget,
left.Expression(),
)
}
if ast.IsPropertyAccessExpression(left) {
assignmentTarget = ch.Factory().NewPropertyAccessExpression(
propertyAccessTarget,
nil,
left.Name(),
ast.NodeFlagsNone,
)
left = ch.Factory().NewPropertyAccessExpression(
propertyAccessTargetAssignment,
nil,
left.Name(),
ast.NodeFlagsNone,
)
} else {
elementAccessArgumentSimpleCopiable := transformers.IsSimpleCopiableExpression(left.AsElementAccessExpression().ArgumentExpression)
elementAccessArgument := left.AsElementAccessExpression().ArgumentExpression
argumentExpr := elementAccessArgument
if !elementAccessArgumentSimpleCopiable {
elementAccessArgument = ch.Factory().NewTempVariable()
ch.EmitContext().AddVariableDeclaration(elementAccessArgument)
argumentExpr = ch.Factory().NewAssignmentExpression(
elementAccessArgument,
left.AsElementAccessExpression().ArgumentExpression,
)
}
assignmentTarget = ch.Factory().NewElementAccessExpression(
propertyAccessTarget,
nil,
elementAccessArgument,
ast.NodeFlagsNone,
)
left = ch.Factory().NewElementAccessExpression(
propertyAccessTargetAssignment,
nil,
argumentExpr,
ast.NodeFlagsNone,
)
}
}
return ch.Factory().NewBinaryExpression(
nil,
left,
nil,
ch.Factory().NewToken(nonAssignmentOperator),
ch.Factory().NewParenthesizedExpression(
ch.Factory().NewAssignmentExpression(
assignmentTarget,
right,
),
),
)
}
func newLogicalAssignmentTransformer(opts *transformers.TransformOptions) *transformers.Transformer {
tx := &logicalAssignmentTransformer{}
return tx.NewTransformer(tx.visit, opts.Context)
}