github.com/arnodel/golua@v0.0.0-20230215163904-e0b5347eaaa1/astcomp/compvar.go (about)

     1  package astcomp
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/arnodel/golua/ast"
     7  	"github.com/arnodel/golua/ir"
     8  )
     9  
    10  type assignFunc func(ir.Register)
    11  
    12  type assignCompiler struct {
    13  	*compiler
    14  	assigns []assignFunc
    15  }
    16  
    17  var _ ast.VarProcessor = (*assignCompiler)(nil)
    18  
    19  // ProcessIndexExpVar compiles the expression as an L-value.
    20  func (c *assignCompiler) ProcessIndexExpVar(e ast.IndexExp) {
    21  	tReg := c.GetFreeRegister()
    22  	c.compileExpInto(e.Coll, tReg)
    23  	c.TakeRegister(tReg)
    24  	iReg := c.GetFreeRegister()
    25  	c.compileExpInto(e.Idx, iReg)
    26  	c.TakeRegister(iReg)
    27  	c.assigns = append(c.assigns, func(src ir.Register) {
    28  		c.ReleaseRegister(tReg)
    29  		c.ReleaseRegister(iReg)
    30  		c.emitInstr(e, ir.SetIndex{
    31  			Table: tReg,
    32  			Index: iReg,
    33  			Src:   src,
    34  		})
    35  	})
    36  }
    37  
    38  // ProcessNameVar compiles the expression as an L-value.
    39  func (c *assignCompiler) ProcessNameVar(n ast.Name) {
    40  	reg, ok := c.GetRegister(ir.Name(n.Val))
    41  	if ok {
    42  		if c.IsConstantReg(reg) {
    43  			panic(Error{
    44  				Where:   n,
    45  				Message: fmt.Sprintf("attempt to reassign constant variable '%s'", n.Val),
    46  			})
    47  		}
    48  		c.assigns = append(c.assigns, func(src ir.Register) {
    49  			c.emitMove(n, reg, src)
    50  		})
    51  	} else {
    52  		c.ProcessIndexExpVar(globalVar(n))
    53  	}
    54  }
    55  
    56  // compileAssignments compiles a slice of ast.Var (L-values).
    57  func (c *compiler) compileAssignments(lvals []ast.Var, dsts []ir.Register) {
    58  	ac := assignCompiler{compiler: c, assigns: make([]assignFunc, 0, len(lvals))}
    59  	for _, lval := range lvals {
    60  		lval.ProcessVar(&ac)
    61  	}
    62  	// Compile the assignments
    63  	for i, reg := range dsts {
    64  		c.ReleaseRegister(reg)
    65  		ac.assigns[i](reg)
    66  	}
    67  }