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 }