public void CallbackReturn() { var thread = new Thread(); var globals = new Table(); var func = Helpers.LoadFunc( "Thread/CallbackReturn.lua", globals ); int numCallbacks = 0; globals[new LString( "callback" )] = (Callable)(l => { Assert.AreEqual( 3, l.StackTop ); for( int i = 1; i <= 3; i++ ) l.Push( l[i].ToDouble() + i ); numCallbacks++; return 3; }); thread.Call( func, 0, 3 ); Assert.AreEqual( 2, numCallbacks ); Assert.AreEqual( 42, thread[1] ); Assert.AreEqual( 54, thread[2] ); Assert.AreEqual( 66, thread[3] ); }
private static void RunTestScriptWithGlobals( string script, Table globals, params Value[] expectedResults ) { Libs.BaseLib.SetBaseMethods( globals ); Libs.MathLib.SetMathMethods( globals ); Libs.TableLib.SetTableMethods( globals ); Libs.StringLib.SetStringMethods( globals ); globals["print"] = (Callable)(l => 0); globals["assert"] = (Callable)(l => { if( !l[1].ToBool() ) Assert.Fail(); return 0; }); var thread = new Thread(); var func = Helpers.LoadFunc( "lua-core/" + script, globals ); Function.Optimize( func ); thread.Call( func, 0, Thread.CallReturnAll ); Assert.AreEqual( expectedResults.Length, thread.StackTop ); for( int i = 0; i < expectedResults.Length; i++ ) Assert.AreEqual( expectedResults[i], thread[i + 1] ); }
public void Callback2() { var thread = new Thread(); var globals = new Table(); var func = Helpers.LoadFunc( "Thread/Callback.lua", globals ); var fn = new CallbackFunc(); globals[new LString( "callback" )] = (Callable)fn; thread.Call( func, 0, 0 ); Assert.AreEqual( 1, fn.RunCount ); }
private static void RunTestScript( string script, params Value[] expectedResults ) { var thread = new Thread(); var globals = new Table(); Libs.BaseLib.SetBaseMethods( globals ); var func = Helpers.LoadFunc( "MetaTable/" + script, globals ); Function.Optimize( func ); thread.Call( func, 0, Thread.CallReturnAll ); Assert.AreEqual( expectedResults.Length, thread.StackTop ); for( int i = 0; i < expectedResults.Length; i++ ) Assert.AreEqual( expectedResults[i], thread[i + 1] ); }
public void Callback1() { var thread = new Thread(); var globals = new Table(); var func = Helpers.LoadFunc( "Thread/Callback.lua", globals ); int numCallbacks = 0; globals[new LString( "callback" )] = (Callable)(l => { Assert.AreEqual( 1, l.StackTop ); Assert.AreEqual( 42, l[1] ); numCallbacks++; return 0; }); thread.Call( func, 0, 0 ); Assert.AreEqual( 1, numCallbacks ); }
private static int BPairs( Thread l ) { var val = l[1]; var mt = GetMetatableImp( val ); Value mmt; if( mt != null && mt.TryGetValue( Literals.TagMethod_Pairs, out mmt ) ) { l.StackTop = 1; l.Call( (Callable)mmt, 1, 3 ); } else { l.SetStack( (Callable)new StableNext(), val, Value.Nil ); } return 3; }
private static int BIPairs( Thread l ) { var val = l[1]; var mt = GetMetatableImp( val ); Value mmt; if( mt != null && mt.TryGetValue( Literals.TagMethod_IPairs, out mmt ) ) { l.StackTop = 1; l.Call( (Callable)mmt, 1, 3 ); return 3; } else { return l.SetReturnValues( INext, val, 0 ); } }
private static void RunTestScriptWithGlobals( string script, Table globals, params Value[] expectedResults ) { globals["assertEqual"] = (Callable)(l => { Assert.AreEqual( l[1], l[2] ); return 0; }); var thread = new Thread(); var func = Helpers.LoadFunc( "Thread/" + script, globals ); Function.Optimize( func ); thread.Call( func, 0, Thread.CallReturnAll ); Assert.AreEqual( expectedResults.Length, thread.StackTop ); for( int i = 0; i < expectedResults.Length; i++ ) Assert.AreEqual( expectedResults[i], thread[i + 1] ); }
public void TwoSimpleCalls() { var thread = new Thread(); var func = Helpers.LoadFunc( "Thread/Call.lua", new Table() ); thread.Call( func, 0, 1 ); Assert.AreEqual( 1, thread.StackTop ); Assert.AreEqual( 42, thread[1] ); thread.Pop(); Assert.AreEqual( 0, thread.StackTop ); thread.Call( func, 0, 1 ); Assert.AreEqual( 1, thread.StackTop ); Assert.AreEqual( 42, thread[1] ); }
private static int SGsub( Thread l ) { var str = (LString)l[1]; var pat = (LString)l[2]; var subst = l[3]; var subTy = subst.ValueType; switch( subTy ) { case LValueType.Number: l.ConvertToString( ref subst ); break; case LValueType.String: case LValueType.Function: case LValueType.Table: break; default: throw new ArgumentException( "string/function/table expected" ); } var max = l.StackTop >= 4 ? (int)l[4] : int.MaxValue; MatchState ms; InitMatchState( out ms, l ); ms.Str = str.InternalData; ms.StrInit = LString.BufferDataOffset; ms.Pat = pat.InternalData; int patInit = LString.BufferDataOffset; bool anchor = patInit < ms.Pat.Length && ms.Pat[patInit] == (byte)'^'; if( anchor ) patInit++; var strBuilder = l.GetStrBuilder( str.Length * 2 ); int sPos = LString.BufferDataOffset; int n = 0; while( n < max ) { ms.Level = 0; Debug.Assert( ms.MatchDepth == MaxCCalls ); var e = SMatch( ref ms, sPos, patInit ); if( e != -1 ) { n++; Value substVal; switch( subTy ) { case LValueType.Function: { l.Push( subst ); var nCap = PushCaptures( ref ms, sPos, e, false ); l.Call( nCap, 1 ); substVal = l.PopValue(); } break; case LValueType.Table: PushCapture( ref ms, 0, sPos, e ); substVal = l.GetTable( (Table)subst, l.PopValue() ); break; case LValueType.Number: //it's already been made a string substVal = subst; break; case LValueType.String: //need to handle escape sequences { var sb = (byte[])subst.RefVal; for( int i = LString.BufferDataOffset; i < sb.Length; i++ ) { var ch = sb[i]; if( ch != (byte)'%' ) { strBuilder.Append( ch ); continue; } if( ++i == sb.Length ) throw new ArgumentException( "Invalid use of % in replacement string" ); ch = sb[i]; if( ch == (byte)'%' ) { strBuilder.Append( ch ); continue; } switch( ch ) { case (byte)'0': strBuilder.Append( ms.Str, sPos, e - sPos ); break; case (byte)'1': case (byte)'2': case (byte)'3': case (byte)'4': case (byte)'5': case (byte)'6': case (byte)'7': case (byte)'8': case (byte)'9': { int idx = ch - (byte)'1'; PushCapture( ref ms, idx, sPos, e ); substVal = l.PopValue(); l.ConvertToString( ref substVal ); strBuilder.Append( (LString)substVal ); } break; default: throw new ArgumentException( "Invalid use o f% in replacement string" ); } } } substVal = new Value(); //hush, little compiler break; default: substVal = new Value(); break; } if( subTy != LValueType.String ) { //strings already appended, need to handle this case now if( !substVal.ToBool() ) { strBuilder.Append( ms.Str, sPos, e - sPos ); } else { l.ConvertToString( ref substVal ); strBuilder.Append( (LString)substVal ); } } } if( e != -1 && e > sPos ) sPos = e; else if( sPos < ms.Str.Length ) strBuilder.Append( ms.Str[sPos++] ); else break; if( anchor ) break; } strBuilder.Append( ms.Str, sPos, ms.Str.Length - sPos ); var ret = strBuilder.ToLString(); l.RetireStrBuilder( strBuilder ); RetireMatchState( ref ms ); return l.SetReturnValues( ret, n ); }