Call a foreign-language function: Difference between revisions

updated ....
(updated ....)
Line 2,783:
<lang asm>
option casemap:none
option literals:on
 
windows64 equ 1
Line 2,789 ⟶ 2,788:
 
ifndef __LUA_CLASS__
__LUA_CLASS__ equ 1
 
 
LUA_OK equ 0
LUA_OK equ 0
LUA_YEILD equ 1
LUA_ERRRUN equ 2
LUA_ERRSYNTAX equ 3
LUA_ERRMEM equ 4
;; Lua variable types - defined in lua.h
LUA_TNONE equ -1
LUA_TNIL equ 0
LUA_TBOOL equ 1
LUA_TNUMB equ 3
LUA_TSTRING equ 4
LUA_TFUNC equ 6
LUA_MULTRET equ -1
 
;; to pop or not to pop, that is the question..
DO_POP equ 1
NO_POP equ 0
 
if @Platform eq windows64
Line 2,802 ⟶ 2,818:
exit equ ExitProcess
elseif @Platform eq linux64
malloc proto SYSTEMV :qword
free proto SYSTEMV :qword
endif
 
printf proto :qword, :vararg
exit proto :dword
;; Lua.h funcs
luaL_newstate proto ;; lua_State *luaL_newstate();
lua_gettop proto :qword ;; int lua_getopt(lua_State *L);
lua_close proto :qword ;; void lua_close(lua_State *L);
luaL_openlibs proto :qword ;; int luaL_openlibs(lua_State *L);
lua_settoplua_pushnil proto :qword, :dword ;; intvoid lua_setoptlua_pushnil(lua_State *L, int idx);
luaL_loadstringlua_pushinteger proto :qword, :qword ;; intvoid luaL_loadstringlua_pushinteger(lua_statelua_State *L, charlua_Integer *stringarg);
lua_pcallklua_settop proto :qword, :dword, :dword, :dword, :dword ;; int lua_setopt(lua_State *L, :dwordint idx);
lua_setglobal proto :qword, :qword ;; void lua_setglobal(lua_State *L, const char *var);
lua_getglobal proto :qword, :qword ;; int lua_getglobal(lua_State *L, const char *gn);
luaL_loadstring proto :qword, :qword ;; int to_loadstring(lua_state *L, const char *string);
lua_pushstring proto :qword, :qword ;; const char *pushstring(lua_State *L, const char *var);
lua_pushboolean proto :qword, :dword ;; void lua_pushboolean(lua_State *L, int b)
lua_isinteger proto :qword, :dword ;; lua_Integer lua_isinteger(lua_State *L, int idx);
lua_tointegerx proto :qword, :dword,:dword ;; lua_Integer lua_tointeger(lua_State *L, int n);
luaL_loadfilex proto :qword, :qword,:dword ;; int luaL_loadfile(lua_State *L, const char *fn, const char *m)
;; void lua_pushcclosure(lua_State *L, lua_CFunction f, int n);
lua_pushccloure proto :qword, :qword, :dword
;; int lua_pcallk(lua_State *L, int argcnt, int results, int errfunc, int context, lua_CFunction k);
lua_pcallk proto :qword, :dword, :dword, :dword, :dword, :dword
 
CLASS lua_class
CMETHOD runstrrun
CMETHOD loadstring
CMETHOD loadfile
CMETHOD setglobal
CMETHOD getglobal
CMETHOD getstate
ENDMETHODS
lua_state qword 0
Line 2,831 ⟶ 2,864:
.if rax != LUA_OK
invoke printf, CSTR("---> Lua failed to open libs",10)
jmp _ext
.endif
 
mov rax, rbx
_ext:
mov rax, rbx
assume rbx:nothing
ret
ENDMETHOD
;; dopop = pop off the virtual stack.
METHOD lua_class, run, <VOIDARG>, <>, narg:dword, nret:dword, dopop:word
mov rbx, thisPtr
assume rbx:ptr lua_class
invoke lua_pcallk, [rbx].lua_state, narg, nret, 0, 0, 0
.if rax != LUA_OK
invoke printf, CSTR("--> lua_pcallk failed with %i",10), rax
.else
;; In some cases, we want to pop the top off the stack. But not always
;; so, DO_POP or NO_POP depending..
.if dopop == DO_POP
invoke lua_gettop, [rbx].lua_state
not eax
invoke lua_settop, [rbx].lua_state, eax
.endif
.endif
assume rbx:nothing
ret
ENDMETHOD
 
METHOD lua_class, runstrloadstring, <VOIDARG>, <>, s:qword
invoke luaL_loadstring, [thisPtr].lua_class.lua_state, s
local tmp:qword
ret
ENDMETHOD
 
METHOD lua_class, loadfile, <VOIDARG>, <>, fn:qword
mov rbx, thisPtr
assume rbx:ptr lua_class
invoke luaL_loadfilex, [rbx].lua_class.lua_state, fn, 0
mov rax, s
invoke lua_pcallk, [rbx].lua_state, 0, LUA_MULTRET, 0, 0, 0
mov tmp, rax
.if rax == LUA_OK
invoke luaL_loadstring, [rbx].lua_state, tmp
invoke lua_pcallk, [rbx].lua_state, 0, 0, 0, 0, 0
.if rax != LUA_OK
invoke printf, CSTR("--> luaL_pcallk failed with %i",10), rax
.else
invoke lua_gettop, [rbx].lua_state
not eax
Line 2,855 ⟶ 2,910:
mov rax, 0
assume rbx:nothing
ret
ENDMETHOD
 
;; lua_class.setglobals(qword ArumentVar, qword ArgumentReferenceName, dword LUA_TTYPE)
;; arg = String(char *) or boolean or integer.
;; an = argument reference name - The name used to reference arg1 from Lua code.
;; t = defined type of argument used.
METHOD lua_class, setglobal, <VOIDARG>, <>, arg:qword, an:qword, t:dword
local targ:qword
local ttype:dword
local tan:qword
 
mov rbx, thisPtr
assume rbx:ptr lua_class
mov targ, arg
mov ttype, t
mov tan, an
.if ttype == LUA_TNIL
invoke lua_pushnil, [rbx].lua_state
.elseif ttype == LUA_TBOOL
mov rax, targ
invoke lua_pushboolean, [rbx].lua_state, eax
.elseif ttype == LUA_TSTRING
invoke lua_pushstring, [rbx].lua_state, targ
.elseif ttype == LUA_TFUNC
;; Used for a lua function call.. But I'm lazy so, check the
;; Lua docs for info about that...
.else
;; Assumes it's an Integer type. Lua's integers are int or long sized(set in luaconfig.h).
;; so qword sized variable to be safe.
invoke lua_pushinteger, [rbx].lua_state, targ
.endif
invoke lua_setglobal, [rbx].lua_state, tan
assume rbx:nothing
ret
ENDMETHOD
 
METHOD lua_class, getglobal, <VOIDARG>, <>, gn:qword
invoke lua_getglobal, [thisPtr].lua_class.lua_state, gn
ret
ENDMETHOD
METHOD lua_class, getstate, <VOIDARG>, <>
mov rax, [thisPtr].lua_class.lua_state
ret
ENDMETHOD
Line 2,868 ⟶ 2,967:
ENDMETHOD
 
endif ;; __LUA_CLASS__
 
.data
d1 dq 1342
d2 dq 1551
pFile db "addition.lua",0
 
.code
main proc
local lvm:ptr lua_class
local state:qword
 
invoke printf, CSTR("-> Attempting to init Lua...",10)
mov lvm, _NEW(lua_class)
lvm->getstate()
invoke printf, CSTR("-> Lua started, Running first test..",10)
mov state, rax
lvm->runstr(CSTR("print('Goodbye, world from Lua..')"))
invoke printf, CSTR("-> LVM started, Using loadstring..",10)
lvm->loadstring(CSTR("print('---> Goodbye, world from Lua..')"))
lvm->run(0,0, DO_POP)
lvm->setglobal(CSTR("A string that's global"), CSTR("teststr"), LUA_TSTRING)
lvm->setglobal(12, CSTR("numb"), LUA_TNONE)
lvm->loadstring(CSTR("print('---> Global str: ' .. teststr .. '\n---> Global int: ' .. numb)"))
lvm->run(0, 0, DO_POP)
invoke printf, CSTR("-> Loading lua file...",10)
lea rax, pFile
lvm->loadfile(rax)
.if rax != LUA_OK
invoke printf, CSTR("-> RunstringFailed failedloadfile, exiting...returned with: %i",10), rax
jmp _ext
.endif
lvm->getglobal(CSTR("addition"))
 
.if rax != LUA_TFUNC
invoke printf, CSTR("-> Global wasn't a function",10,"-> Type retruned is: %d",10), rax
jmp _ext
.endif
;; We're just pushing the ints onto the Virtual stack for arguments
invoke lua_pushinteger, state, d1
invoke lua_pushinteger, state, d2
lvm->run(2,1,NO_POP)
.if rax == LUA_OK
invoke lua_isinteger, state, -1
.if rax != 1
invoke printf, CSTR("-> Value is NOT an integer..",10)
jmp _ext
.endif
invoke lua_tointegerx, state, -1, 0
push rax
;; Set the top of the virtual stack to our return value..
invoke lua_settop, state, 1
pop rax
invoke printf, CSTR("-> Return from lua func: %i",10), eax
.else
invoke printf, CSTR("-> lvm->run() failed to call func returned: %i",10), rax
.endif
_ext:
_DELETE(lvm)
Line 2,888 ⟶ 3,027:
main endp
 
end
</lang>
Addition.lua
<lang lua>
function addition(a, b)
print('---> Lua calc: ' .. a .. ' + ' .. b .. ' = ' .. a+b)
return a + b
end
</lang>
Line 2,893 ⟶ 3,039:
<pre>
-> Attempting to init Lua...
-> LuaLVM started, RunningUsing first testloadstring..
---> Goodbye, world from Lua..
---> Global str: A string that's global
---> Global int: 12
-> Loading lua file...
---> Lua calc: 1342 + 1551 = 2893
-> Return from lua func: 2893
</pre>
When I stop being lazy and/or drunk, I'll update the class to run a lua script file...
 
=={{header|zkl}}==