Given this expression in JavaScript:
ipad[15] = opad[15] = some[12] = some[13] = undefined
I get this AST (from acornjs):
{
"type": "Program",
"body": [
{
"type": "AssignmentExpression",
"left": {
"type": "MemberExpression",
"object": {
"type": "Identifier",
"start": 3943,
"end": 3947,
"name": "ipad"
},
"property": {
"type": "Literal",
"start": 3948,
"end": 3950,
"value": 15,
"raw": "15"
},
"computed": true
},
"right": {
"type": "AssignmentExpression",
"left": {
"type": "MemberExpression",
"object": {
"type": "Identifier",
"start": 3954,
"end": 3958,
"name": "opad"
},
"property": {
"type": "Literal",
"start": 3959,
"end": 3961,
"value": 15,
"raw": "15"
},
"computed": true
},
"right": {
"type": "AssignmentExpression",
"left": {
"type": "MemberExpression",
"object": {
"type": "Identifier",
"start": 3965,
"end": 3969,
"name": "some"
},
"property": {
"type": "Literal",
"start": 3970,
"end": 3972,
"value": 12,
"raw": "12"
},
"computed": true
},
"right": {
"type": "AssignmentExpression",
"left": {
"type": "MemberExpression",
"object": {
"type": "Identifier",
"start": 3976,
"end": 3980,
"name": "some"
},
"property": {
"type": "Literal",
"start": 3981,
"end": 3983,
"value": 13,
"raw": "13"
},
"computed": true
},
"right": {
"type": "Identifier",
"start": 3987,
"end": 3996,
"name": "undefined"
},
"operator": "="
},
"operator": "="
},
"operator": "="
},
"operator": "="
}
]
}
How can I convert this AST to something that when reserialized would produce:
ipad[15] = undefined
opad[15] = undefined
some[12] = undefined
some[13] = undefined
Basically, flattening the AST. How can it be done? I have been thinking about this for hours and trying to modify this source code to get it working, but it's a bit mind bending.
Each AssignmentExpression
has a right property. So I feel like just setting them at the top level to the last right item would work, but it's for some reason eluding me.
I am logging in that normalize_AssignmentExpression
function, and it is showing:
RIGHT Node { type: 'Identifier', start: 3987, end: 3996, name: 'undefined' }
RIGHT {
type: 'AssignmentExpression',
left: {
type: 'MemberExpression',
object: Node { type: 'Identifier', start: 3976, end: 3980, name: 'some' },
property: Node {
type: 'Literal',
start: 3981,
end: 3983,
value: 13,
raw: '13'
},
computed: true
},
right: Node {
type: 'Identifier',
start: 3987,
end: 3996,
name: 'undefined'
},
operator: '='
}
RIGHT {
type: 'AssignmentExpression',
left: {
type: 'MemberExpression',
object: Node { type: 'Identifier', start: 3965, end: 3969, name: 'some' },
property: Node {
type: 'Literal',
start: 3970,
end: 3972,
value: 12,
raw: '12'
},
computed: true
},
right: {
type: 'AssignmentExpression',
left: {
type: 'MemberExpression',
object: [Node],
property: [Node],
computed: true
},
right: Node {
type: 'Identifier',
start: 3987,
end: 3996,
name: 'undefined'
},
operator: '='
},
operator: '='
}
RIGHT {
type: 'AssignmentExpression',
left: {
type: 'MemberExpression',
object: Node { type: 'Identifier', start: 3954, end: 3958, name: 'opad' },
property: Node {
type: 'Literal',
start: 3959,
end: 3961,
value: 15,
raw: '15'
},
computed: true
},
right: {
type: 'AssignmentExpression',
left: {
type: 'MemberExpression',
object: [Node],
property: [Node],
computed: true
},
right: {
type: 'AssignmentExpression',
left: [Object],
right: [Node],
operator: '='
},
operator: '='
},
operator: '='
}
Not sure if that helps.
I try to make it like this, but it just outputs one:
function normalize_AssignmentExpression(node, scope) {
const [left, leftExps] = normalizeProperty(node.type, 'left', node.left.type, node.left, scope)
let [right, rightExps] = normalizeProperty(node.type, 'right', node.right.type, node.right, scope)
const exps = [
...leftExps,
...rightExps
]
let furthestRight = right
while (furthestRight.type === 'AssignmentExpression') {
furthestRight = furthestRight.right
}
if (left.type === 'ArrayPattern') {
const assignments = []
left.elements.forEach(el => {
assignments.push(
createAssignmentExpression(
el,
createMemberExpression(right, el),
node.operator
)
)
})
return [
assignments,
exps
]
} else {
console.log('RIGHT', right)
const assignment = createAssignmentExpression(left, furthestRight, node.operator)
return [
assignment,
exps
]
}
}
CodePudding user response:
This does it:
function normalize_AssignmentExpression(node, scope) {
const [left, leftExps] = normalizeProperty(node.type, 'left', node.left.type, node.left, scope)
let [right, rightExps] = normalizeProperty(node.type, 'right', node.right.type, node.right, scope)
const exps = [
...leftExps,
...rightExps
]
let furthestRight = Array.isArray(right) ? right[0] : right
let rights = Array.isArray(right) ? right.slice(1) : []
let lefts = [left]
while (furthestRight.type === 'AssignmentExpression') {
lefts.push(furthestRight.left)
furthestRight = furthestRight.right
}
if (left.type === 'ArrayPattern') {
const assignments = []
left.elements.forEach(el => {
assignments.push(
createAssignmentExpression(
el,
createMemberExpression(right, el),
node.operator
)
)
})
return [
assignments,
exps
]
} else {
const assignments = []
lefts.forEach(l => {
const assignment = createAssignmentExpression(l, furthestRight, node.operator)
assignments.push(assignment)
})
assignments.push(...rights)
return [
assignments,
exps
]
}
}