public LHSAssign() { Prev = null; Exp = new ExpDesc(); }
// check whether, in an assignment to an upvalue/local variable, the // upvalue/local variable is begin used in a previous assignment to a // table. If so, save original upvalue/local value in a safe place and // use this safe copy in the previous assignment. private void CheckConflict( LHSAssign lh, ExpDesc v ) { var fs = CurFunc; // eventual position to save local variable int extra = fs.FreeReg; bool conflict = false; // check all previous assignments for( ; lh != null; lh = lh.Prev ) { var e = lh.Exp; // assign to a table? if( e.Kind == ExpKind.VINDEXED ) { // table is the upvalue/local being assigned now? if( e.Ind.Vt == v.Kind && e.Ind.T == v.Info ) { conflict = true; e.Ind.Vt = ExpKind.VLOCAL; e.Ind.T = extra; // previous assignment will use safe copy } // index is the local being assigned? (index cannot be upvalue) if( v.Kind == ExpKind.VLOCAL && e.Ind.Idx == v.Info ) { conflict = true; e.Ind.Idx = extra; // previous assignment will use safe copy } } } if( conflict ) { // copy upvalue/local value to a temporary (in position 'extra') var op = (v.Kind == ExpKind.VLOCAL) ? OpCode.OP_MOVE : OpCode.OP_GETUPVAL; Coder.CodeABC( fs, op, extra, v.Info, 0 ); Coder.ReserveRegs( fs, 1 ); } }
// assignment -> ',' suffixedexp assignment private void Assignment( LHSAssign lh, int nvars ) { CheckCondition( ExpKindUtl.VKIsVar( lh.Exp.Kind ), "syntax error" ); ExpDesc e = new ExpDesc(); if( TestNext( (int)',' ) ) { var nv = new LHSAssign(); nv.Prev = lh; SuffixedExp( nv.Exp ); if( nv.Exp.Kind != ExpKind.VINDEXED ) CheckConflict( lh, nv.Exp ); CheckLimit( CurFunc, nvars + Lua.NumCSharpCalls, LuaLimits.LUAI_MAXCCALLS, "C# levels" ); Assignment( nv, nvars+1 ); } else { CheckNext( (int)'=' ); int nexps = ExpList( e ); if( nexps != nvars ) { AdjustAssign( nvars, nexps, e ); if( nexps > nvars ) { // remove extra values CurFunc.FreeReg -= (nexps - nvars); } } else { Coder.SetOneRet( CurFunc, e ); Coder.StoreVar( CurFunc, lh.Exp, e ); return; } } // default assignment InitExp( e, ExpKind.VNONRELOC, CurFunc.FreeReg-1 ); Coder.StoreVar( CurFunc, lh.Exp, e ); }
// stat -> func | assignment private void ExprStat() { var v = new LHSAssign(); SuffixedExp( v.Exp ); // stat -> assignment ? if( Lexer.Token.TokenType == (int)'=' || Lexer.Token.TokenType == (int)',' ) { v.Prev = null; Assignment( v, 1 ); } // stat -> func else { if( v.Exp.Kind != ExpKind.VCALL ) Lexer.SyntaxError("syntax error"); var pi = CurFunc.GetCode( v.Exp ); pi.Value = pi.Value.SETARG_C( 1 ); // call statment uses no results } }