Example #1
0
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)
	}
}
Example #2
0
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(")")
}