整理代码1

This commit is contained in:
2026-02-04 17:50:50 +08:00
parent d02fb85b1c
commit eb26a500bb
45 changed files with 0 additions and 0 deletions

343
interpreter/UniLua/Do.cs Normal file
View File

@@ -0,0 +1,343 @@
// #define DEBUG_D_PRE_CALL
// #define DEBUG_D_POS_CALL
namespace UniLua
{
using ULDebug = UniLua.Tools.ULDebug;
using InstructionPtr = Pointer<Instruction>;
using Exception = System.Exception;
public class LuaRuntimeException : Exception
{
public ThreadStatus ErrCode { get; private set; }
public LuaRuntimeException( ThreadStatus errCode )
{
ErrCode = errCode;
}
}
public partial class LuaState
{
internal void D_Throw( ThreadStatus errCode )
{
throw new LuaRuntimeException( errCode );
}
private ThreadStatus D_RawRunProtected<T>( PFuncDelegate<T> func, ref T ud )
{
int oldNumCSharpCalls = NumCSharpCalls;
ThreadStatus res = ThreadStatus.LUA_OK;
try
{
func(ref ud);
}
catch( LuaRuntimeException e )
{
NumCSharpCalls = oldNumCSharpCalls;
res = e.ErrCode;
}
NumCSharpCalls = oldNumCSharpCalls;
return res;
}
private void SetErrorObj( ThreadStatus errCode, StkId oldTop )
{
switch( errCode )
{
case ThreadStatus.LUA_ERRMEM: // memory error?
oldTop.V.SetSValue("not enough memory");
break;
case ThreadStatus.LUA_ERRERR:
oldTop.V.SetSValue("error in error handling");
break;
default: // error message on current top
oldTop.V.SetObj(ref Stack[Top.Index-1].V);
break;
}
Top = Stack[oldTop.Index+1];
}
private ThreadStatus D_PCall<T>( PFuncDelegate<T> func, ref T ud,
int oldTopIndex, int errFunc )
{
int oldCIIndex = CI.Index;
bool oldAllowHook = AllowHook;
int oldNumNonYieldable = NumNonYieldable;
int oldErrFunc = ErrFunc;
ErrFunc = errFunc;
ThreadStatus status = D_RawRunProtected<T>( func, ref ud );
if( status != ThreadStatus.LUA_OK ) // an error occurred?
{
F_Close( Stack[oldTopIndex] );
SetErrorObj( status, Stack[oldTopIndex] );
CI = BaseCI[oldCIIndex];
AllowHook = oldAllowHook;
NumNonYieldable = oldNumNonYieldable;
}
ErrFunc = oldErrFunc;
return status;
}
private void D_Call( StkId func, int nResults, bool allowYield )
{
if( ++NumCSharpCalls >= LuaLimits.LUAI_MAXCCALLS )
{
if( NumCSharpCalls == LuaLimits.LUAI_MAXCCALLS )
G_RunError( "CSharp Stack Overflow" );
else if( NumCSharpCalls >=
(LuaLimits.LUAI_MAXCCALLS + (LuaLimits.LUAI_MAXCCALLS>>3))
)
D_Throw( ThreadStatus.LUA_ERRERR );
}
if( !allowYield )
NumNonYieldable++;
if( !D_PreCall( func, nResults ) ) // is a Lua function ?
V_Execute();
if( !allowYield )
NumNonYieldable--;
NumCSharpCalls--;
}
/// <summary>
/// return true if function has been executed
/// </summary>
private bool D_PreCall( StkId func, int nResults )
{
// prepare for Lua call
#if DEBUG_D_PRE_CALL
Console.WriteLine( "============================ D_PreCall func:" + func );
#endif
int funcIndex = func.Index;
if(!func.V.TtIsFunction()) {
// not a function
// retry with `function' tag method
func = tryFuncTM( func );
// now it must be a function
return D_PreCall( func, nResults );
}
if(func.V.ClIsLuaClosure()) {
var cl = func.V.ClLValue();
Utl.Assert(cl != null);
var p = cl.Proto;
D_CheckStack(p.MaxStackSize + p.NumParams);
func = Stack[funcIndex];
//
int n = (Top.Index - func.Index) - 1;
for( ; n<p.NumParams; ++n )
{ StkId.inc(ref Top).V.SetNilValue(); }
int stackBase = (!p.IsVarArg) ? (func.Index + 1) : AdjustVarargs( p, n );
CI = ExtendCI();
CI.NumResults = nResults;
CI.FuncIndex = func.Index;
CI.BaseIndex = stackBase;
CI.TopIndex = stackBase + p.MaxStackSize;
Utl.Assert(CI.TopIndex <= StackLast);
CI.SavedPc = new InstructionPtr( p.Code, 0 );
CI.CallStatus = CallStatus.CIST_LUA;
Top = Stack[CI.TopIndex];
return false;
}
if(func.V.ClIsCsClosure()) {
var cscl = func.V.ClCsValue();
Utl.Assert(cscl != null);
D_CheckStack(LuaDef.LUA_MINSTACK);
func = Stack[funcIndex];
CI = ExtendCI();
CI.NumResults = nResults;
CI.FuncIndex = func.Index;
CI.TopIndex = Top.Index + LuaDef.LUA_MINSTACK;
CI.CallStatus = CallStatus.CIST_NONE;
// do the actual call
int n = cscl.F( this );
// poscall
D_PosCall( Top.Index-n );
return true;
}
throw new System.NotImplementedException();
}
private int D_PosCall( int firstResultIndex )
{
// TODO: hook
// be careful: CI may be changed after hook
int resIndex = CI.FuncIndex;
int wanted = CI.NumResults;
#if DEBUG_D_POS_CALL
Console.WriteLine( "[D] ==== PosCall enter" );
Console.WriteLine( "[D] ==== PosCall res:" + res );
Console.WriteLine( "[D] ==== PosCall wanted:" + wanted );
#endif
CI = BaseCI[CI.Index-1];
int i = wanted;
for( ; i!=0 && firstResultIndex < Top.Index; --i )
{
#if DEBUG_D_POS_CALL
Console.WriteLine( "[D] ==== PosCall assign lhs res:" + res );
Console.WriteLine( "[D] ==== PosCall assign rhs firstResult:" + firstResult );
#endif
Stack[resIndex++].V.SetObj(ref Stack[firstResultIndex++].V);
}
while( i-- > 0 )
{
#if DEBUG_D_POS_CALL
Console.WriteLine( "[D] ==== PosCall new LuaNil()" );
#endif
Stack[resIndex++].V.SetNilValue();
}
Top = Stack[resIndex];
#if DEBUG_D_POS_CALL
Console.WriteLine( "[D] ==== PosCall return " + (wanted - LuaDef.LUA_MULTRET) );
#endif
return (wanted - LuaDef.LUA_MULTRET);
}
private CallInfo ExtendCI()
{
int newIndex = CI.Index + 1;
if(newIndex >= BaseCI.Length) {
int newLength = BaseCI.Length*2;
var newBaseCI = new CallInfo[newLength];
int i = 0;
while(i < BaseCI.Length) {
newBaseCI[i] = BaseCI[i];
newBaseCI[i].List = newBaseCI;
++i;
}
while(i < newLength) {
var newCI = new CallInfo();
newBaseCI[i] = newCI;
newCI.List = newBaseCI;
newCI.Index = i;
++i;
}
BaseCI = newBaseCI;
CI = newBaseCI[CI.Index];
return newBaseCI[newIndex];
}
else {
return BaseCI[newIndex];
}
}
private int AdjustVarargs( LuaProto p, int actual )
{
// `...'
// : func (base)fixed-p1 fixed-p2 var-p1 var-p2 top
// : func nil nil var-p1 var-p2 (base)fixed-p1 fixed-p2 (reserved...) top
//
// `...'
// func (base)fixed-p1 fixed-p2 (reserved...) top
int NumFixArgs = p.NumParams;
Utl.Assert( actual >= NumFixArgs, "AdjustVarargs (actual >= NumFixArgs) is false" );
int fixedArg = Top.Index - actual; // first fixed argument
int stackBase = Top.Index; // final position of first argument
for( int i=stackBase; i<stackBase+NumFixArgs; ++i )
{
Stack[i].V.SetObj(ref Stack[fixedArg].V);
Stack[fixedArg++].V.SetNilValue();
}
Top = Stack[stackBase+NumFixArgs];
return stackBase;
}
private StkId tryFuncTM( StkId func )
{
var tmObj = T_GetTMByObj( ref func.V, TMS.TM_CALL );
if(!tmObj.V.TtIsFunction())
G_TypeError( func, "call" );
// open a hole inside the stack at `func'
for(int i=Top.Index; i>func.Index; --i)
{ Stack[i].V.SetObj(ref Stack[i-1].V); }
IncrTop();
func.V.SetObj(ref tmObj.V);
return func;
}
private void D_CheckStack(int n)
{
if(StackLast - Top.Index <= n)
D_GrowStack(n);
// TODO: FOR DEBUGGING
// else
// CondMoveStack();
}
// some space for error handling
private const int ERRORSTACKSIZE = LuaConf.LUAI_MAXSTACK + 200;
private void D_GrowStack(int n)
{
int size = Stack.Length;
if(size > LuaConf.LUAI_MAXSTACK)
D_Throw(ThreadStatus.LUA_ERRERR);
int needed = Top.Index + n + LuaDef.EXTRA_STACK;
int newsize = 2 * size;
if(newsize > LuaConf.LUAI_MAXSTACK)
{ newsize = LuaConf.LUAI_MAXSTACK; }
if(newsize < needed)
{ newsize = needed; }
if(newsize > LuaConf.LUAI_MAXSTACK)
{
D_ReallocStack(ERRORSTACKSIZE);
G_RunError("stack overflow");
}
else
{
D_ReallocStack(newsize);
}
}
private void D_ReallocStack(int size)
{
Utl.Assert(size <= LuaConf.LUAI_MAXSTACK || size == ERRORSTACKSIZE);
var newStack = new StkId[size];
int i = 0;
for( ; i<Stack.Length; ++i) {
newStack[i] = Stack[i];
newStack[i].SetList(newStack);
}
for( ; i<size; ++i) {
newStack[i] = new StkId();
newStack[i].SetList(newStack);
newStack[i].SetIndex(i);
newStack[i].V.SetNilValue();
}
Top = newStack[Top.Index];
Stack = newStack;
StackLast = size - LuaDef.EXTRA_STACK;
}
}
}