Added exception handling for registered functions

Added HasValue method for tables
Fixed LuaFunction DataType not being recognized as VariableFunction
This commit is contained in:
Mark van Renswoude 2017-05-28 16:34:32 +02:00
parent b250054d26
commit 47b39799f3
4 changed files with 81 additions and 6 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
/__history/ __history

View File

@ -194,8 +194,8 @@ var
lua_pushunsigned: procedure(L: lua_State; n: lua_Unsigned); cdecl; lua_pushunsigned: procedure(L: lua_State; n: lua_Unsigned); cdecl;
lua_pushlstring: function (L: lua_State; s: PAnsiChar; l_: size_t): PAnsiChar; cdecl; lua_pushlstring: function (L: lua_State; s: PAnsiChar; l_: size_t): PAnsiChar; cdecl;
lua_pushstring: function (L: lua_State; s: PAnsiChar): PAnsiChar; cdecl; lua_pushstring: function (L: lua_State; s: PAnsiChar): PAnsiChar; cdecl;
lua_pushvfstring: function (L: lua_State; fmt: PAnsiChar; argp: array of const): PAnsiChar; cdecl; lua_pushvfstring: function (L: lua_State; fmt: PAnsiChar; argp: Pointer): PAnsiChar; cdecl;
lua_pushfstring: function (L: lua_State; fmt: PAnsiChar): PAnsiChar; cdecl; lua_pushfstring: function (L: lua_State; fmt: PAnsiChar; argp: Pointer): PAnsiChar; cdecl;
lua_pushcclosure: procedure(L: lua_State; fn: lua_CFunction; n: Integer); cdecl; lua_pushcclosure: procedure(L: lua_State; fn: lua_CFunction; n: Integer); cdecl;
lua_pushboolean: procedure(L: lua_State; b: Integer); cdecl; lua_pushboolean: procedure(L: lua_State; b: Integer); cdecl;
lua_pushlightuserdata: procedure(L: lua_State; p: Pointer); cdecl; lua_pushlightuserdata: procedure(L: lua_State; p: Pointer); cdecl;
@ -408,6 +408,10 @@ type
var var
luaL_setfuncs: procedure(L: lua_State; luaL_Reg: PluaL_Reg; nup: Integer); cdecl; luaL_setfuncs: procedure(L: lua_State; luaL_Reg: PluaL_Reg; nup: Integer); cdecl;
procedure luaL_where(L: lua_State; level: Integer);
function luaL_error(L: lua_State; fmt: PAnsiChar; argp: Pointer): Integer;
const const
DefaultLuaLibName = 'lua' + LUA_VERSION_MAJOR + LUA_VERSION_MINOR + '.dll'; DefaultLuaLibName = 'lua' + LUA_VERSION_MAJOR + LUA_VERSION_MINOR + '.dll';
@ -727,6 +731,33 @@ begin
Result := lua_tolstring(L, idx, nil); Result := lua_tolstring(L, idx, nil);
end; end;
procedure luaL_where(L: lua_State; level: Integer);
var
ar: lua_Debug;
msg: AnsiString;
begin
if (lua_getstack(L, level, ar) <> 0) then // check function at level
begin
lua_getinfo(L, 'Sl', ar); // get info about it
if (ar.currentline > 0) then // is there info?
begin
msg := Format('%s:%d: ', [ar.short_src, ar.currentline]);
lua_pushlstring(L, PAnsiChar(msg), Length(msg));
exit
end;
end;
lua_pushliteral(L, ''); // else, no information available...
end;
function luaL_error(L: lua_State; fmt: PAnsiChar; argp: Pointer): Integer;
begin
luaL_where(L, 1);
lua_pushvfstring(L, fmt, argp);
lua_concat(L, 2);
Result := lua_error(L);
end;
initialization initialization
finalization finalization

28
Lua.pas
View File

@ -40,6 +40,7 @@ type
ELuaUnsupportedParameterException = class(ELuaException); ELuaUnsupportedParameterException = class(ELuaException);
ELuaUnsupportedVariableException = class(ELuaException); ELuaUnsupportedVariableException = class(ELuaException);
ELuaNoFunctionException = class(ELuaException); ELuaNoFunctionException = class(ELuaException);
ELuaNativeCodeException = class(ELuaException);
TLuaLibrary = (Base, Coroutine, Table, IO, OS, StringLib, Bit32, Math, Debug, Package, All); TLuaLibrary = (Base, Coroutine, Table, IO, OS, StringLib, Bit32, Math, Debug, Package, All);
TLuaLibraries = set of TLuaLibrary; TLuaLibraries = set of TLuaLibrary;
@ -127,6 +128,7 @@ type
['{57FD52A1-7D53-485B-A630-29841C498387}'] ['{57FD52A1-7D53-485B-A630-29841C498387}']
function GetEnumerator: ILuaTableEnumerator; function GetEnumerator: ILuaTableEnumerator;
function HasValue(AKey: TLuaImplicitVariable): Boolean;
function GetValue(AKey: TLuaImplicitVariable): ILuaVariable; function GetValue(AKey: TLuaImplicitVariable): ILuaVariable;
procedure SetValue(AKey: TLuaImplicitVariable; AValue: TLuaImplicitVariable); procedure SetValue(AKey: TLuaImplicitVariable; AValue: TLuaImplicitVariable);
end; end;
@ -165,6 +167,7 @@ type
{ ILuaTable } { ILuaTable }
function GetEnumerator: ILuaTableEnumerator; function GetEnumerator: ILuaTableEnumerator;
function HasValue(AKey: TLuaImplicitVariable): Boolean;
function GetValue(AKey: TLuaImplicitVariable): ILuaVariable; function GetValue(AKey: TLuaImplicitVariable): ILuaVariable;
procedure SetValue(AKey: TLuaImplicitVariable; AValue: TLuaImplicitVariable); procedure SetValue(AKey: TLuaImplicitVariable; AValue: TLuaImplicitVariable);
end; end;
@ -666,6 +669,7 @@ begin
LuaBoolean: Result := VariableBoolean; LuaBoolean: Result := VariableBoolean;
LuaString: Result := VariableString; LuaString: Result := VariableString;
LuaTable: Result := VariableTable; LuaTable: Result := VariableTable;
LuaFunction: Result := VariableFunction;
LuaUserData: Result := VariableUserData; LuaUserData: Result := VariableUserData;
LuaLightUserData: Result := VariableUserData; LuaLightUserData: Result := VariableUserData;
else else
@ -1081,6 +1085,11 @@ begin
end; end;
function TLuaTable.HasValue(AKey: TLuaImplicitVariable): Boolean;
begin
Result := FTable.ContainsKey(AKey);
end;
function TLuaTable.GetValue(AKey: TLuaImplicitVariable): ILuaVariable; function TLuaTable.GetValue(AKey: TLuaImplicitVariable): ILuaVariable;
begin begin
Result := FTable[AKey]; Result := FTable[AKey];
@ -1308,8 +1317,16 @@ end;
procedure TLua.LoadFromFile(const AFileName: string; AAutoRun: Boolean; const AChunkName: string); procedure TLua.LoadFromFile(const AFileName: string; AAutoRun: Boolean; const AChunkName: string);
var
chunkName: string;
begin begin
LoadFromScript(TLuaScript.Create(TFileStream.Create(AFileName, fmOpenRead or fmShareDenyNone), soOwned), soOwned, AAutoRun, AChunkName); if Length(AChunkName) > 0 then
chunkName := AChunkName
else
chunkName := ExtractFileName(AFileName);
LoadFromScript(TLuaScript.Create(TFileStream.Create(AFileName, fmOpenRead or fmShareDenyNone), soOwned), soOwned, AAutoRun, chunkName);
end; end;
@ -1670,8 +1687,13 @@ begin
begin begin
context := TLuaContext.Create(State); context := TLuaContext.Create(State);
RegisteredFunctions[ACookie](context); try
Result := context.Result.Count; RegisteredFunctions[ACookie](context);
Result := context.Result.Count;
except
on E:Exception do
Result := luaL_error(State, PAnsiChar(AnsiString(E.Message)), nil);
end;
end; end;
end; end;

View File

@ -33,6 +33,7 @@ type
procedure Input; procedure Input;
procedure Output; procedure Output;
procedure DelphiFunction; procedure DelphiFunction;
procedure DelphiFunctionException;
procedure LuaFunction; procedure LuaFunction;
procedure LuaFunctionDefaultResult; procedure LuaFunctionDefaultResult;
procedure LuaFunctionString; procedure LuaFunctionString;
@ -197,6 +198,27 @@ begin
end; end;
procedure TTestWrapper.DelphiFunctionException;
begin
Lua.RegisterFunction('crazyharry',
procedure(AContext: ILuaContext)
begin
raise Exception.Create('Boom!');
end);
try
Lua.LoadFromString('print(crazyharry("Did somebody say dynamite?"))');
Fail('ELuaNativeCodeException expected');
except
on E:Exception do
begin
CheckIs(E, ELuaException);
CheckEquals('[string "?"]:1: Boom!', E.Message);
end;
end;
end;
procedure TTestWrapper.LuaFunction; procedure TTestWrapper.LuaFunction;
var var
returnValues: ILuaReadParameters; returnValues: ILuaReadParameters;