func (c *compiler) VisitAssignment(node *ast.Assignment, data interface{}) { if node.Op == ast.TokenColoneq { // short variable declaration var names []*ast.Id for _, id := range node.Left { names = append(names, id.(*ast.Id)) } c.declare(names, node.Right) return } else if node.Op != ast.TokenEq { // compound assignment // a += b -> a = a + b bin := ast.BinaryExpr{Op: ast.CompoundOp(node.Op), Left: node.Left[0], Right: node.Right[0]} fake := ast.Assignment{Op: ast.TokenEq, Left: node.Left, Right: []ast.Node{&bin}} fake.Accept(c, nil) return } // regular assignment, if the left-side is an identifier // then it has to be declared already varCount, valueCount := len(node.Left), len(node.Right) _, isCall := node.Right[valueCount-1].(*ast.CallExpr) _, isUnpack := node.Right[valueCount-1].(*ast.VarArg) start := c.block.register current := start end := start + varCount - 1 // evaluate all expressions first with temp registers for i, _ := range node.Left { reg := start + i exprdata := exprdata{false, reg, reg} if i == valueCount-1 && (isCall || isUnpack) { exprdata.regb, current = end, end node.Right[i].Accept(c, &exprdata) break } if i < valueCount { node.Right[i].Accept(c, &exprdata) current = reg + 1 } } // assign the results to the variables for i, variable := range node.Left { valueReg := start + i // don't touch variables without a corresponding value if valueReg >= current { break } c.assignmentHelper(variable, current+1, valueReg) } }
func (p *prettyprinter) VisitAssignment(node *ast.Assignment, data interface{}) { p.buf.WriteString("(assignment") p.indent++ for _, node := range node.Left { p.buf.WriteString("\n") p.doIndent() node.Accept(p, nil) } p.buf.WriteString("\n") p.doIndent() p.buf.WriteString(node.Op.String()) for _, node := range node.Right { p.buf.WriteString("\n") p.doIndent() node.Accept(p, nil) } p.indent-- p.buf.WriteString(")") }