was/api.lua

518 lines
14 KiB
Lua
Raw Normal View History

2019-01-03 13:57:48 -08:00
was.register_function=function(name,t)
2019-01-12 01:35:39 -08:00
if t.depends and not minetest.get_modpath(t.depends) then return end
2019-01-03 13:57:48 -08:00
was.functions[name]=t.action
2019-01-04 02:32:59 -08:00
was.function_packed[name]=t.packed
2019-01-03 13:57:48 -08:00
was.info[name]=t.info
was.privs[name]=t.privs
end
was.register_symbol=function(symbol,f,info)
2019-01-04 03:04:00 -08:00
was.symbols[symbol]=f
was.info[symbol]=info
2019-01-04 02:32:59 -08:00
end
2019-01-13 01:14:10 -08:00
was.save=function(def,save)
if def.type=="node" then
if save then
minetest.get_meta(def.pos):set_string("save", minetest.serialize(def.save))
else
return minetest.deserialize(minetest.get_meta(def.pos):get_string("save")) or {}
end
return
end
2019-01-03 13:57:48 -08:00
end
2019-01-13 01:14:10 -08:00
was.protected=function(pos) if was.is_pos(pos) then return minetest.is_protected(pos,was.userdata.name) end end
was.chr=function(t) local a=string.byte(t) return (a>=65 and a<=90) or (a>=97 and a<=122) or t=="_" end
was.num=function(t) local a=string.byte(t) return a>=48 and a<=57 end
was.symbol=function(t) return was.symbols_characters:find(t) end
was.is_number=function(n) return type(n)=="number" end
was.is_string=function(s) return type(s)=="string" end
was.is_pos=function(pos) return type(pos)=="table" and type(pos.x)=="number" and type(pos.y)=="number" and type(pos.z)=="number" end
was.is_table=function(t) return type(t)=="table" end
2019-01-03 13:57:48 -08:00
2019-01-06 02:48:22 -08:00
was.ilastuserdata=function()
for i=was.userdata.index,#was.userdata.data,1 do
if not was.userdata.data[i+1] or was.userdata.data[i].type=="bracket end" then
return i
end
end
2019-01-06 02:48:22 -08:00
return 1
end
2019-01-06 02:48:22 -08:00
was.iuserdata=function(i)
local v=was.userdata.data[i]
2019-01-07 11:02:08 -08:00
if v then
2019-01-06 02:48:22 -08:00
if v.type=="var" then
v=was.userdata.var[v.content]
else
v=v.content
end
end
return v
end
2019-01-12 01:35:39 -08:00
was.compiler=function(input_text,def)
def=def or{}
2019-01-16 12:53:08 -08:00
2019-01-16 01:26:32 -08:00
if type(input_text)~="string" or input_text:len()<2 or type(def.user)~="string" or not was.is_pos(def.pos) or not def.type then
2019-01-03 13:57:48 -08:00
return
end
2019-01-16 01:26:32 -08:00
if def.type=="node" then
local meta=minetest.get_meta(def.pos)
2019-01-16 08:47:28 -08:00
local t=meta:get_int("last_run")
2019-01-16 12:53:08 -08:00
local runs=meta:get_int("runs")+1
local sec=was.time("sec",t)
meta:set_int("runs",runs)
if sec<1 and runs>10 then
return
2019-01-16 01:26:32 -08:00
elseif sec>1 then
2019-01-16 08:47:28 -08:00
meta:set_int("runs",1)
meta:set_int("last_run", was.time("gettime"))
end
local intensity=meta:get_int("intensity")+1
local last_intensity_check=meta:get_int("last_intensity_check")
meta:set_int("intensity",intensity)
if was.time("min",last_intensity_check)>1 then
meta:set_int("last_intensity_check",os.time())
meta:set_int("intensity",0)
if intensity>120 then
if minetest.get_node(def.pos).name=="was:computer" then
if was.user[def.user] and was.user[def.user].gui then
minetest.close_formspec(def.user,"gui")
was.user[def.user]=nil
end
minetest.swap_node(def.pos,{name="was:computer_closed"})
return
end
end
2019-01-16 01:26:32 -08:00
end
end
2019-01-03 13:57:48 -08:00
input_text=input_text .."\n"
2019-01-06 13:57:21 -08:00
input_text=input_text:gsub("%("," { ")
input_text=input_text:gsub("%)"," } ")
input_text=input_text:gsub("%[","")
input_text=input_text:gsub("%]","")
2019-01-09 00:29:35 -08:00
input_text=input_text:gsub("%%","")
2019-01-03 13:57:48 -08:00
local c
local data={}
local output_data={}
local n
local chr
local s
local ob={type="",content=""}
2019-01-06 13:57:21 -08:00
local i=1
while i<=input_text:len() do
2019-01-03 13:57:48 -08:00
c=input_text:sub(i,i)
n=was.num(c)
chr=was.chr(c)
s=was.symbol(c)
2019-01-06 13:57:21 -08:00
2019-01-03 13:57:48 -08:00
if c=='"' and ob.type~="string" then
2019-01-06 13:57:21 -08:00
--string
2019-01-03 13:57:48 -08:00
if ob.content~="" then table.insert(data,ob) end
ob={type="",content=""}
ob.type="string"
2019-01-06 13:57:21 -08:00
c=""
2019-01-03 13:57:48 -08:00
elseif c=='"' and ob.type=="string" then
if ob.content~="" then table.insert(data,ob) end
ob={type="",content=""}
2019-01-06 13:57:21 -08:00
elseif n and ob.type=="" then
2019-01-03 13:57:48 -08:00
--number
ob.type="number"
elseif not n and ob.type=="number" and c~="." then
if ob.content~="" then table.insert(data,ob) end
ob={type="",content=""}
2019-01-06 13:57:21 -08:00
i=i-1
elseif ob.type=="" and chr then
2019-01-03 13:57:48 -08:00
--var
ob.type="var"
2019-01-12 13:36:40 -08:00
elseif ob.type=="var" and not chr then -- and c~="."
2019-01-03 13:57:48 -08:00
if ob.content~="" then table.insert(data,ob) end
ob={type="",content=""}
2019-01-06 13:57:21 -08:00
i=i-1
elseif ob.type=="" and s then
2019-01-03 13:57:48 -08:00
--symbols
ob.type="symbol"
elseif ob.type=="symbol" and not s then
if ob.content~="" then table.insert(data,ob) end
ob={type="",content=""}
2019-01-06 13:57:21 -08:00
i=i-1
elseif c=="\n" then
2019-01-03 13:57:48 -08:00
--end of line
if ob.content~="" then table.insert(data,ob) end
table.insert(output_data,data)
ob={type="",content=""}
data={}
end
2019-01-06 13:57:21 -08:00
if ob.type~="" then
2019-01-12 01:35:39 -08:00
if c=="." and ob.type=="var" then
ob.table=true
end
2019-01-06 13:57:21 -08:00
ob.content=ob.content .. c
end
i=i+1
2019-01-03 13:57:48 -08:00
end
local output_data2={}
local func
2019-01-16 12:53:08 -08:00
2019-01-03 13:57:48 -08:00
--print(dump(output_data))
local ifends=0
2019-01-07 09:44:10 -08:00
local nexts=0
2019-01-12 13:36:40 -08:00
local VAR={}
2019-01-03 13:57:48 -08:00
for i,v in ipairs(output_data) do
local ii=1
data=v
while ii<=#v do
2019-01-14 13:47:16 -08:00
if data[ii].type=="number" and not (data[ii-1] and data[ii-1].content==".") then
2019-01-03 13:57:48 -08:00
--number
data[ii].content=tonumber(data[ii].content)
2019-01-07 06:16:06 -08:00
if data[ii-1] and data[ii-1].content=="-" then
data[ii].content=-data[ii].content
table.remove(data,ii-1)
ii=ii-1
end
2019-01-03 13:57:48 -08:00
elseif data[ii].type=="var" and (data[ii].content=="and" or data[ii].content=="or" or data[ii].content=="not" or data[ii].content=="nor") then
--oparator
data[ii].type="symbol"
elseif data[ii].type=="var" and (data[ii].content=="false" or data[ii].content=="true") then
--bool
data[ii].type="bool"
data[ii].content=data[ii].content=="true"
elseif data[ii].content=="elseif" or data[ii].content=="else" or (ifends>0 and data[ii].content=="end") then
--elseif, else end
data[ii].type="ifstate"
data[ii].ifstate=true
if data[ii].content=="end" then
ifends=ifends-1
end
2019-01-04 15:30:48 -08:00
elseif data[ii+1] and data[ii+2] and data[ii].type=="var" and data[ii+1].content=="=" and not was.symbols[data[ii+1].content .. data[ii+2].content] then
2019-01-03 13:57:48 -08:00
--var =
if func then
return 'ERROR line '.. i ..': set variable "' ..data[ii].content .. '" inside function'
end
data[ii].type="set var"
table.remove(data,ii+1)
elseif data[ii+1] and data[ii].type=="var" and data[ii+1].content=="{" then
--function(
if not was.functions[data[ii].content] then
return 'ERROR line '.. i ..': void function "' .. data[ii].content ..'"'
end
func=true
data[ii].type="function"
2019-01-12 01:35:39 -08:00
data[ii].table=nil
if data[ii].content=="if" then
data[ii].ifstate=true
ifends=ifends+1
2019-01-07 09:44:10 -08:00
elseif data[ii].content=="for" then
if nexts==1 then
return 'ERROR line '.. i ..': only 1 "for" at time'
end
nexts=1
data[ii].forstate=true
end
2019-01-03 13:57:48 -08:00
table.remove(data,ii+1)
elseif data[ii].content=="}" then
--)
func=nil
data[ii].type="bracket end"
2019-01-14 08:16:45 -08:00
elseif data[ii].type=="symbol" and not data[ii].content=="{" then
2019-01-09 00:29:35 -08:00
--symbol
if not was.symbols[data[ii].content] then
return 'ERROR line '.. i ..': "' .. data[ii].content ..'" unknown symbol'
elseif data[ii].content=="--" then
ii=#v
end
2019-01-07 09:44:10 -08:00
elseif data[ii].type=="var" and data[ii].content=="next" then
2019-01-12 13:36:40 -08:00
--for next
2019-01-07 09:44:10 -08:00
if nexts==0 then
return 'ERROR line '.. i ..': no "for" to return to'
end
nexts=0
data[ii].forstate=true
2019-01-20 11:16:19 -08:00
elseif data[ii].type=="var" and data[ii].content=="break" then
--break
if nexts==0 then
return 'ERROR line '.. i ..': no "for" to break'
end
data[ii].forstate=true
elseif data[ii].type=="var" and data[ii].content=="return" then
--return
data[ii].function_return=true
2019-01-14 13:47:16 -08:00
elseif data[ii+1] and data[ii+2] and data[ii].type=="var" and data[ii+1].content=="." and (data[ii+2].type=="var" or data[ii+2].type=="number") then
2019-01-12 01:35:39 -08:00
--table
2019-01-12 13:36:40 -08:00
data[ii].table=data[ii+2].content
local vn=data[ii].content
local tab={}
tab[data[ii+2].content]={}
local t=tab[data[ii+2].content]
table.remove(data,ii+1)
table.remove(data,ii+1)
for ni=ii,#v,1 do
2019-01-14 13:47:16 -08:00
if data[ii+1] and data[ii+2] and data[ii+1].content=="." and (data[ii+2].type=="var" or data[ii+2].type=="number") then
2019-01-12 13:36:40 -08:00
data[ii].table=data[ii].table .. "." .. data[ii+2].content
t[data[ii+2].content]={}
t=t[data[ii+2].content]
table.remove(data,ii+1)
table.remove(data,ii+1)
else
break
end
end
if data[ii+1] and data[ii+1].content=="=" then
data[ii].type="set var"
table.remove(data,ii+1)
end
--reset table, make able for function again
if data[ii+1] and data[ii+1].content=="{" then
data[ii].content=vn .."." .. data[ii].table
data[ii].table=nil
ii=ii-1
else
VAR[vn]=tab
end
2019-01-03 13:57:48 -08:00
end
ii=ii+1
end
if func then
return 'ERROR line '.. i ..': missing ")"'
end
table.insert(output_data2,data)
end
2019-01-12 01:35:39 -08:00
for i,c in pairs(output_data2) do
for name,v in pairs(c) do
if v.type=="function" and was.privs[v.content] and not minetest.check_player_privs(def.user,was.privs[v.content]) then
return 'ERROR: the function "' .. v.content ..'" requires privileges: ' .. minetest.privs_to_string(was.privs[v.content])
2019-01-03 13:57:48 -08:00
end
end
2019-01-12 01:35:39 -08:00
end
if ifends>0 then
return 'ERROR: Missing ' .. ifends .. ' if "end"'
end
2019-01-07 09:44:10 -08:00
if nexts>0 then
return 'ERROR: Missing ' .. nexts .. ' for "next"'
end
2019-01-12 13:36:40 -08:00
--print(dump(output_data2))
2019-01-16 12:53:08 -08:00
2019-01-13 01:14:10 -08:00
local msg,def,VAR=was.run(output_data2,def,VAR)
def.save=VAR.save
was.save(def,true)
2019-01-07 09:44:10 -08:00
2019-01-12 01:35:39 -08:00
return msg
2019-01-03 13:57:48 -08:00
end
2019-01-12 13:36:40 -08:00
was.get_VAR=function(VAR,avar)
if avar.table then
local a=avar.table.split(avar.table,".")
local t=VAR[avar.content]
for i,v in ipairs(a) do
2019-01-13 01:14:10 -08:00
if t and t[v] then
2019-01-12 13:36:40 -08:00
t=t[v]
2019-01-14 13:47:16 -08:00
elseif t and t[tonumber(v)] then
t=t[tonumber(v)]
2019-01-13 01:14:10 -08:00
else
break
2019-01-12 13:36:40 -08:00
end
end
return t
else
return VAR[avar.content]
end
end
was.set_VAR=function(VAR,avar,value)
if avar.table then
local a=avar.table.split(avar.table,".")
local t=VAR[avar.content]
for i,v in ipairs(a) do
if a[i+1] then
2019-01-14 13:47:16 -08:00
local n=tonumber(v)
if n then
t=t[n]
else
t=t[v]
end
2019-01-12 13:36:40 -08:00
else
break
end
end
2019-01-14 13:47:16 -08:00
if t and t[a[#a]] then
t[a[#a]]=value
end
2019-01-12 13:36:40 -08:00
return VAR
else
2019-01-13 01:14:10 -08:00
VAR[avar.content]=value
2019-01-12 13:36:40 -08:00
return VAR
end
end
was.run_function=function(func_name,data,VAR,i,ii)
2019-01-03 13:57:48 -08:00
local d={}
local open=0
2019-01-06 02:48:22 -08:00
was.userdata.function_name=func_name
2019-01-03 13:57:48 -08:00
while i<=ii do
if data[i].type=="bracket end" then
if open<=0 then
break
else
open=open-1
end
elseif data[i].type=="function" then
open=open+1
end
if data[i].type=="number" or data[i].type=="string" or data[i].type=="bool" then
2019-01-03 13:57:48 -08:00
table.insert(d,data[i].content)
elseif data[i].type=="symbol" and was.symbols[data[i].content] then
2019-01-06 02:48:22 -08:00
was.userdata.index=i
2019-01-12 02:12:28 -08:00
table.insert(d, was.symbols[data[i].content]() or data[i].content)
2019-01-04 02:32:59 -08:00
elseif data[i].type=="var" then
2019-01-12 13:36:40 -08:00
table.insert(d,was.get_VAR(VAR,data[i]) or func_name=="if" and "!")
elseif data[i].type=="function" then
2019-01-06 02:48:22 -08:00
was.userdata.index=i
2019-01-04 02:32:59 -08:00
local re,newi=was.run_function(data[i].content,data,VAR,i+1,#data)
2019-01-03 13:57:48 -08:00
i=newi
if re then
table.insert(d,re or func_name=="if" and "!")
2019-01-03 13:57:48 -08:00
end
end
2019-01-06 02:48:22 -08:00
2019-01-03 13:57:48 -08:00
i=i+1
end
2019-01-04 02:32:59 -08:00
if was.function_packed[func_name] then
return was.functions[func_name](d),i
2019-01-03 13:57:48 -08:00
else
2019-01-04 02:32:59 -08:00
return was.functions[func_name](unpack(d)),i
2019-01-03 13:57:48 -08:00
end
end
2019-01-12 13:36:40 -08:00
was.run=function(input,def,VAR)
VAR.event=def.event
2019-01-13 01:14:10 -08:00
VAR.save=was.save(def)
2019-01-03 13:57:48 -08:00
local state=0
2019-01-04 15:30:48 -08:00
local elsestate=0
2019-01-07 09:44:10 -08:00
local forstate
was.userdata={
2019-01-12 01:35:39 -08:00
name=def.user,
function_name="",
index=0,
data={},
2019-01-12 01:35:39 -08:00
id=def.pos.x .." " ..def.pos.y .." " .. def.pos.z,
pos=def.pos,
print=def.print,
2019-01-20 06:09:23 -08:00
type=def.type,
}
2019-01-07 09:44:10 -08:00
local index=0
while index<#input do
2019-01-12 13:36:40 -08:00
index=index+1
local v=input[index]
2019-01-03 13:57:48 -08:00
local i=1
while i<=#v do
was.userdata.data=v
was.userdata.index=i
2019-01-06 02:48:22 -08:00
was.userdata.var=VAR
2019-01-09 00:29:35 -08:00
if was.userdata.error then
2019-01-13 01:14:10 -08:00
return 'ERROR line '.. index ..': ' .. was.userdata.error,def,VAR
2019-01-20 11:16:19 -08:00
elseif state==0 and v[i].function_return then
was.userdata={}
return "",def,VAR
elseif state==0 and v[i].forstate then
if forstate and forstate.br and v[i].content=="break" then
index=forstate.br
forstate=nil
elseif v[i].content=="next" then
forstate.br=index+1
2019-01-07 09:44:10 -08:00
if forstate.i<forstate.e then
2019-01-20 11:16:19 -08:00
forstate.br=index
2019-01-07 09:44:10 -08:00
index=forstate.re
forstate.i=forstate.i+1
else
forstate=nil
end
elseif v[i].content=="for" then
local fo=was.run_function(v[i].content,v,VAR,i+1,#v)
forstate={
re=index,
i=fo.s,
e=fo.e,
}
if fo.msg then
2019-01-13 01:14:10 -08:00
return fo.msg,def,VAR
2019-01-07 09:44:10 -08:00
end
end
elseif v[i].ifstate then
if v[i].content=="if" then
if state==0 and was.run_function(v[i].content,v,VAR,i+1,#v)==true then
state=0
else
state=state+1
end
end
if v[i].content=="elseif" then
if state==0 then
state=1
elsestate=1
elseif state==1 and elsestate==0 and was.run_function(v[i].content,v,VAR,i+1,#v)==true then
state=0
end
elseif v[i].content=="else" then
if state==0 then
state=1
elseif state==1 and elsestate==0 then
state=0
end
elseif v[i].content=="end" then
state=state-1
if state<=0 then
state=0
elsestate=0
end
end
elseif state>0 then
elseif v[i].type=="set var" and v[i+1] then
2019-01-03 13:57:48 -08:00
local ndat=v[i+1]
if (ndat.type=="string" or ndat.type=="number" or ndat.type=="bool") then
2019-01-12 13:36:40 -08:00
VAR=was.set_VAR(VAR,v[i],ndat.content)
2019-01-04 03:04:00 -08:00
elseif ndat.type=="symbol" and was.symbols[ndat.content] then
2019-01-12 13:36:40 -08:00
VAR=was.set_VAR(VAR,v[i],was.symbols[ndat.content]())
2019-01-03 13:57:48 -08:00
elseif ndat.type=="var" and VAR[ndat.content] then
2019-01-12 13:36:40 -08:00
VAR=was.set_VAR(VAR,v[i],VAR[ndat.content])
2019-01-03 13:57:48 -08:00
elseif ndat.type=="function" and was.functions[ndat.content] then
2019-01-12 13:36:40 -08:00
VAR=was.set_VAR(VAR,v[i],was.run_function(ndat.content,v,VAR,i+2,#v))
2019-01-03 13:57:48 -08:00
else
2019-01-12 13:36:40 -08:00
VAR=was.set_VAR(VAR,v[i],nil)
2019-01-03 13:57:48 -08:00
end
i=i+1
elseif v[i].type=="function" then
was.run_function(v[i].content,v,VAR,i+1,#v)
2019-01-03 13:57:48 -08:00
i=i+1
2019-01-07 11:02:08 -08:00
elseif v[i].type=="symbol" and was.symbols[v[i].content] and v[i-1] and v[i-1].type=="var" then
2019-01-12 13:36:40 -08:00
VAR=was.set_VAR(VAR,v[i-1],was.symbols[v[i].content]())
2019-01-03 13:57:48 -08:00
end
i=i+1
end
end
was.userdata={}
2019-01-13 01:14:10 -08:00
return "",def,VAR
2019-01-03 13:57:48 -08:00
--print(dump(VAR))
end