mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-24 10:40:46 +00:00
Lunatic translator: gamearrays.
git-svn-id: https://svn.eduke32.com/eduke32@3503 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
2264331daf
commit
fd2790da82
2 changed files with 179 additions and 20 deletions
|
@ -1276,6 +1276,75 @@ function _setaspect(viewingrange, yxaspect)
|
|||
end
|
||||
|
||||
|
||||
--- Game arrays ---
|
||||
|
||||
local function check_gamearray_idx(gar, idx, addstr)
|
||||
if (idx >= gar._size+0ULL) then
|
||||
addstr = addstr or ""
|
||||
error("invalid "..addstr.."array index "..idx, 3)
|
||||
end
|
||||
end
|
||||
|
||||
local gamearray_methods = {
|
||||
resize = function(gar, newsize)
|
||||
-- NOTE: size 0 is valid (then, no index is valid)
|
||||
if (newsize < 0) then
|
||||
error("invalid new array size "..newsize, 2)
|
||||
end
|
||||
|
||||
-- clear trailing elements in case we're shrinking
|
||||
for i=gar._size,newsize-1 do
|
||||
gar[i] = nil
|
||||
end
|
||||
|
||||
gar._size = newsize
|
||||
end,
|
||||
|
||||
copyto = function(sar, sidx, dar, didx, numelts)
|
||||
-- XXX: Strictest bound checking, see later if we need to relax it.
|
||||
check_gamearray_idx(sar, sidx, "lower source ")
|
||||
check_gamearray_idx(sar, sidx+numelts-1, "upper source ")
|
||||
check_gamearray_idx(dar, didx, "lower destination ")
|
||||
check_gamearray_idx(dar, didx+numelts-1, "upper destination ")
|
||||
for i=0,numelts-1 do
|
||||
dar[dsix+i] = sar[sidx+i]
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local gamearray_mt = {
|
||||
__index = function(gar, key)
|
||||
if (type(key)=="number") then
|
||||
check_gamearray_idx(key)
|
||||
return 0
|
||||
else
|
||||
return gamearray_methods[key]
|
||||
end
|
||||
end,
|
||||
|
||||
__newindex = function(gar, idx, val)
|
||||
check_gamearray_idx(idx)
|
||||
gar[idx] = val
|
||||
end,
|
||||
|
||||
-- Calling a gamearray causes its cleanup:
|
||||
-- * All values equal to the default one (0) are cleared.
|
||||
__call = function(gar)
|
||||
for i=0,gar._size-1 do
|
||||
if (gar[i]==0) then
|
||||
gar[i] = nil
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
__metatable = true,
|
||||
}
|
||||
|
||||
function _gamearray(size)
|
||||
return setmetatable({ _size=size }, gamearray_mt)
|
||||
end
|
||||
|
||||
|
||||
--- Exported functions ---
|
||||
|
||||
-- Non-local control flow. These ones call the original error(), not our
|
||||
|
|
|
@ -117,6 +117,8 @@ GVFLAG.USER_MASK = GVFLAG.PERX_MASK + GVFLAG.NODEFAULT + GVFLAG.NORESET
|
|||
local g_funcname = {}
|
||||
-- [identifier] = { name=<mangled name / code>, flags=<gamevar flags> }
|
||||
local g_gamevar = {}
|
||||
-- [identifier] = { name=<mangled name / code>, size=<initial size> }
|
||||
local g_gamearray = {}
|
||||
|
||||
local g_have_file = {} -- [filename]=true
|
||||
local g_curcode = nil -- a table of string pieces or other "gencode" tables
|
||||
|
@ -248,6 +250,7 @@ end
|
|||
local function reset_codegen()
|
||||
g_funcname = {}
|
||||
g_gamevar = new_initial_gvartab()
|
||||
g_gamearray = {}
|
||||
|
||||
g_have_file = {}
|
||||
g_curcode = new_initial_codetab()
|
||||
|
@ -452,7 +455,18 @@ function lookup.defined_label(pos, maybe_minus_str, identifier)
|
|||
return (maybe_minus_str=="" and 1 or -1) * num
|
||||
end
|
||||
|
||||
local function check_sysvar_def_attempt(identifier)
|
||||
if (identifier=="actorvar") then
|
||||
errprintf("cannot define reserved symbol `actorvar'")
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function do_define_label(identifier, num)
|
||||
if (check_sysvar_def_attempt(identifier)) then
|
||||
return
|
||||
end
|
||||
|
||||
local oldtype = g_labeltype[identifier]
|
||||
local oldval = g_labeldef[identifier]
|
||||
|
||||
|
@ -726,13 +740,6 @@ local function stripws(str)
|
|||
end
|
||||
|
||||
function Cmd.definequote(qnum, quotestr)
|
||||
--[[
|
||||
-- have the INT_MAX limit simply for some sanity
|
||||
if (not (qnum >= 0 and <= 0x7fffffff)) then
|
||||
errprintf("quote number is negative or exceeds limit of INT32_MAX.")
|
||||
return
|
||||
end
|
||||
--]]
|
||||
if (not (qnum >= 0 and qnum < conl.MAXQUOTES)) then
|
||||
errprintf("quote number is negative or exceeds limit of %d.", conl.MAXQUOTES-1)
|
||||
return
|
||||
|
@ -828,7 +835,42 @@ end
|
|||
|
||||
--- GAMEVARS / GAMEARRAYS
|
||||
|
||||
function Cmd.gamearray(identifier, initsize)
|
||||
if (check_sysvar_def_attempt(identifier)) then
|
||||
return
|
||||
end
|
||||
|
||||
if (initsize >= 0x7fffffff+0ULL) then
|
||||
errprintf("invalid initial size %d for gamearray `%s'", initsize, identifier)
|
||||
return
|
||||
end
|
||||
|
||||
local oga = g_gamearray[identifier]
|
||||
if (oga) then
|
||||
if (initsize ~= oga.size) then
|
||||
errprintf("duplicate gamearray definition `%s' has different size", identifier)
|
||||
return
|
||||
else
|
||||
warnprintf("duplicate gamearray definition `%s' ignored", identifier)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if (g_gamevar[identifier]) then
|
||||
warnprintf("symbol `%s' already used for game variable", identifier)
|
||||
end
|
||||
|
||||
local ga = { name=mangle_name(identifier, "A"), size=initsize }
|
||||
g_gamearray[identifier] = ga
|
||||
|
||||
addcodef("local %s=_con._gamearray(%d)", ga.name, initsize)
|
||||
end
|
||||
|
||||
function Cmd.gamevar(identifier, initval, flags)
|
||||
if (check_sysvar_def_attempt(identifier)) then
|
||||
return
|
||||
end
|
||||
|
||||
-- TODO: handle user bits like NORESET or NODEFAULT
|
||||
if (bit.band(flags, bit.bnot(GVFLAG.USER_MASK)) ~= 0) then
|
||||
-- TODO: a couple of the presumably safe ones
|
||||
|
@ -897,6 +939,15 @@ function Cmd.gamevar(identifier, initval, flags)
|
|||
end
|
||||
end
|
||||
|
||||
function lookup.gamearray(identifier)
|
||||
local ga = g_gamearray[identifier]
|
||||
if (ga == nil) then
|
||||
errprintf("symbol `%s' is not a game array", identifier)
|
||||
return "_INVALIDGA"
|
||||
end
|
||||
return ga.name
|
||||
end
|
||||
|
||||
-- <aorpvar>: code for actor or player index
|
||||
function lookup.gamevar(identifier, aorpvar, writable)
|
||||
local gv = g_gamevar[identifier]
|
||||
|
@ -967,6 +1018,7 @@ local tok =
|
|||
|
||||
rvar = Var("t_rvar"),
|
||||
wvar = Var("t_wvar"),
|
||||
gamearray = Var("t_gamearray"),
|
||||
|
||||
-- for definelevelname
|
||||
time = lpeg.C(alphanum*alphanum^-1*":"*alphanum*alphanum^-1),
|
||||
|
@ -994,8 +1046,9 @@ local function n_defines(n) -- works well only for small n
|
|||
end
|
||||
|
||||
|
||||
local D, R, W, I, AC, MV, AI = -1, -2, -3, -4, -5, -6, -7
|
||||
local TOKEN_PATTERN = { [D]=tok.define, [R]=tok.rvar, [W]=tok.wvar, [I]=tok.identifier,
|
||||
local D, R, W, I, GARI, AC, MV, AI = -1, -2, -3, -4, -5, -6, -7, -8
|
||||
local TOKEN_PATTERN = { [D]=tok.define, [R]=tok.rvar, [W]=tok.wvar,
|
||||
[I]=tok.identifier, [GARI]=tok.gamearray,
|
||||
[AC]=tok.action, [MV]=tok.move, [AI]=tok.ai }
|
||||
|
||||
-- Generic command pattern, types given by varargs.
|
||||
|
@ -1065,7 +1118,7 @@ local Couter = {
|
|||
|
||||
--- 4. Game Variables / Arrays
|
||||
gamevar = cmd(I,D,D) / Cmd.gamevar,
|
||||
gamearray = cmd(I,D),
|
||||
gamearray = cmd(I,D) / Cmd.gamearray,
|
||||
|
||||
--- 5. Top level commands that are also run-time commands
|
||||
move = sp1 * tok.identifier * (sp1 * tok.define)^-2 / -- hvel, vvel
|
||||
|
@ -1188,11 +1241,43 @@ local function StructAccess(Structname, writep, index, membertab)
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
function lookup.array_expr(writep, structname, index, membertab)
|
||||
if (conl.StructAccessCode[structname] == nil) then
|
||||
-- warnprintf("gamearray access: NYI")
|
||||
return "_NYI"
|
||||
-- Try a gamearray
|
||||
local ga = (g_gamearray[structname]) and lookup.gamearray(structname)
|
||||
if (ga == nil) then
|
||||
if (structname=="actorvar") then
|
||||
-- actorvar[] inline array expr
|
||||
-- XXX: kind of CODEDUP with GetOrSetPerxvarCmd() factory
|
||||
local gv = g_gamevar[structname]
|
||||
if (gv and bit.band(gv.flags, GVFLAG.PERX_MASK)~=GVFLAG.PERACTOR) then
|
||||
errprintf("variable `%s' is not per-actor", structname, "actor")
|
||||
end
|
||||
|
||||
if (membertab == nil) then
|
||||
errprintf("actorvar[] requires a pseudo member (gamevar) name")
|
||||
return "_INVALIDAV"
|
||||
end
|
||||
|
||||
if (#membertab > 1) then
|
||||
errprintf("actorvar[] cannot be used with a second parameter")
|
||||
return "_INVALIDAV"
|
||||
end
|
||||
|
||||
assert(#membertab == 1)
|
||||
return lookup.gamevar(membertab[1], index, writep)
|
||||
end
|
||||
|
||||
errprintf("symbol `%s' is neither a struct nor a gamearray", structname)
|
||||
return "_INVALIDAR"
|
||||
end
|
||||
|
||||
if (membertab ~= nil) then
|
||||
errprintf("gamearrays cannot be indexed with member names")
|
||||
return "_INVALIDAR"
|
||||
end
|
||||
|
||||
return format("%s[%s]", ga.name, index)
|
||||
end
|
||||
|
||||
local membercode, ismethod = StructAccess(structname, writep, index, membertab)
|
||||
|
@ -1679,12 +1764,16 @@ local Cinner = {
|
|||
getpname = cmd(R,R),
|
||||
|
||||
-- array stuff
|
||||
copy = sp1 * tok.identifier * arraypat * sp1 * tok.identifier * arraypat * sp1 * tok.rvar,
|
||||
setarray = sp1 * tok.identifier * arraypat * sp1 * tok.rvar,
|
||||
resizearray = cmd(I,R),
|
||||
getarraysize = cmd(I,W),
|
||||
readarrayfromfile = cmd(I,D),
|
||||
writearraytofile = cmd(I,D),
|
||||
copy = sp1 * tok.gamearray * arraypat * sp1 * tok.gamearray * arraypat * sp1 * tok.rvar
|
||||
/ "%1:copyto(%2,%3,%4,%5)",
|
||||
setarray = sp1 * tok.gamearray * arraypat * sp1 * tok.rvar
|
||||
/ "%1[%2]=%3",
|
||||
resizearray = cmd(GARI,R)
|
||||
/ "%1:resize(%2)",
|
||||
getarraysize = cmd(GARI,W)
|
||||
/ "%2=%1._size",
|
||||
readarrayfromfile = cmd(GARI,D),
|
||||
writearraytofile = cmd(GARI,D),
|
||||
|
||||
addlogvar = cmd(R)
|
||||
/ handle.addlogvar,
|
||||
|
@ -2269,7 +2358,6 @@ local function get_deferred_code(tab, lev, code)
|
|||
end
|
||||
|
||||
local function begin_if_fn(condstr, endifstr, endifelsestr)
|
||||
condstr = condstr or "TODO"
|
||||
assert(type(condstr)=="string")
|
||||
|
||||
add_deferred_code(g_endIfCode, g_iflevel, endifstr)
|
||||
|
@ -2339,6 +2427,8 @@ local Grammar = Pat{
|
|||
t_wvar = Var("t_singlearrayexp") / function() errprintf("t_wvar: array exprs NYI") return "_NYIVAR" end
|
||||
+ (tok.identifier / function(id) return lookup.gamevar(id, "_aci", true) end),
|
||||
|
||||
t_gamearray = Var("t_identifier") / lookup.gamearray,
|
||||
|
||||
t_move =
|
||||
POS()*tok.identifier / function(...) return lookup.composite(LABEL.MOVE, ...) end +
|
||||
POS()*tok.number / function(...) return check_composite_literal(LABEL.MOVE, ...) end,
|
||||
|
|
Loading…
Reference in a new issue