mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-26 03:30: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
|
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 ---
|
--- Exported functions ---
|
||||||
|
|
||||||
-- Non-local control flow. These ones call the original error(), not our
|
-- 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 = {}
|
local g_funcname = {}
|
||||||
-- [identifier] = { name=<mangled name / code>, flags=<gamevar flags> }
|
-- [identifier] = { name=<mangled name / code>, flags=<gamevar flags> }
|
||||||
local g_gamevar = {}
|
local g_gamevar = {}
|
||||||
|
-- [identifier] = { name=<mangled name / code>, size=<initial size> }
|
||||||
|
local g_gamearray = {}
|
||||||
|
|
||||||
local g_have_file = {} -- [filename]=true
|
local g_have_file = {} -- [filename]=true
|
||||||
local g_curcode = nil -- a table of string pieces or other "gencode" tables
|
local g_curcode = nil -- a table of string pieces or other "gencode" tables
|
||||||
|
@ -248,6 +250,7 @@ end
|
||||||
local function reset_codegen()
|
local function reset_codegen()
|
||||||
g_funcname = {}
|
g_funcname = {}
|
||||||
g_gamevar = new_initial_gvartab()
|
g_gamevar = new_initial_gvartab()
|
||||||
|
g_gamearray = {}
|
||||||
|
|
||||||
g_have_file = {}
|
g_have_file = {}
|
||||||
g_curcode = new_initial_codetab()
|
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
|
return (maybe_minus_str=="" and 1 or -1) * num
|
||||||
end
|
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)
|
local function do_define_label(identifier, num)
|
||||||
|
if (check_sysvar_def_attempt(identifier)) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local oldtype = g_labeltype[identifier]
|
local oldtype = g_labeltype[identifier]
|
||||||
local oldval = g_labeldef[identifier]
|
local oldval = g_labeldef[identifier]
|
||||||
|
|
||||||
|
@ -726,13 +740,6 @@ local function stripws(str)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Cmd.definequote(qnum, quotestr)
|
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
|
if (not (qnum >= 0 and qnum < conl.MAXQUOTES)) then
|
||||||
errprintf("quote number is negative or exceeds limit of %d.", conl.MAXQUOTES-1)
|
errprintf("quote number is negative or exceeds limit of %d.", conl.MAXQUOTES-1)
|
||||||
return
|
return
|
||||||
|
@ -828,7 +835,42 @@ end
|
||||||
|
|
||||||
--- GAMEVARS / GAMEARRAYS
|
--- 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)
|
function Cmd.gamevar(identifier, initval, flags)
|
||||||
|
if (check_sysvar_def_attempt(identifier)) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
-- TODO: handle user bits like NORESET or NODEFAULT
|
-- TODO: handle user bits like NORESET or NODEFAULT
|
||||||
if (bit.band(flags, bit.bnot(GVFLAG.USER_MASK)) ~= 0) then
|
if (bit.band(flags, bit.bnot(GVFLAG.USER_MASK)) ~= 0) then
|
||||||
-- TODO: a couple of the presumably safe ones
|
-- TODO: a couple of the presumably safe ones
|
||||||
|
@ -897,6 +939,15 @@ function Cmd.gamevar(identifier, initval, flags)
|
||||||
end
|
end
|
||||||
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
|
-- <aorpvar>: code for actor or player index
|
||||||
function lookup.gamevar(identifier, aorpvar, writable)
|
function lookup.gamevar(identifier, aorpvar, writable)
|
||||||
local gv = g_gamevar[identifier]
|
local gv = g_gamevar[identifier]
|
||||||
|
@ -967,6 +1018,7 @@ local tok =
|
||||||
|
|
||||||
rvar = Var("t_rvar"),
|
rvar = Var("t_rvar"),
|
||||||
wvar = Var("t_wvar"),
|
wvar = Var("t_wvar"),
|
||||||
|
gamearray = Var("t_gamearray"),
|
||||||
|
|
||||||
-- for definelevelname
|
-- for definelevelname
|
||||||
time = lpeg.C(alphanum*alphanum^-1*":"*alphanum*alphanum^-1),
|
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
|
end
|
||||||
|
|
||||||
|
|
||||||
local D, R, W, I, AC, MV, AI = -1, -2, -3, -4, -5, -6, -7
|
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,
|
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 }
|
[AC]=tok.action, [MV]=tok.move, [AI]=tok.ai }
|
||||||
|
|
||||||
-- Generic command pattern, types given by varargs.
|
-- Generic command pattern, types given by varargs.
|
||||||
|
@ -1065,7 +1118,7 @@ local Couter = {
|
||||||
|
|
||||||
--- 4. Game Variables / Arrays
|
--- 4. Game Variables / Arrays
|
||||||
gamevar = cmd(I,D,D) / Cmd.gamevar,
|
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
|
--- 5. Top level commands that are also run-time commands
|
||||||
move = sp1 * tok.identifier * (sp1 * tok.define)^-2 / -- hvel, vvel
|
move = sp1 * tok.identifier * (sp1 * tok.define)^-2 / -- hvel, vvel
|
||||||
|
@ -1188,11 +1241,43 @@ local function StructAccess(Structname, writep, index, membertab)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function lookup.array_expr(writep, structname, index, membertab)
|
function lookup.array_expr(writep, structname, index, membertab)
|
||||||
if (conl.StructAccessCode[structname] == nil) then
|
if (conl.StructAccessCode[structname] == nil) then
|
||||||
-- warnprintf("gamearray access: NYI")
|
-- Try a gamearray
|
||||||
return "_NYI"
|
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
|
end
|
||||||
|
|
||||||
local membercode, ismethod = StructAccess(structname, writep, index, membertab)
|
local membercode, ismethod = StructAccess(structname, writep, index, membertab)
|
||||||
|
@ -1679,12 +1764,16 @@ local Cinner = {
|
||||||
getpname = cmd(R,R),
|
getpname = cmd(R,R),
|
||||||
|
|
||||||
-- array stuff
|
-- array stuff
|
||||||
copy = sp1 * tok.identifier * arraypat * sp1 * tok.identifier * arraypat * sp1 * tok.rvar,
|
copy = sp1 * tok.gamearray * arraypat * sp1 * tok.gamearray * arraypat * sp1 * tok.rvar
|
||||||
setarray = sp1 * tok.identifier * arraypat * sp1 * tok.rvar,
|
/ "%1:copyto(%2,%3,%4,%5)",
|
||||||
resizearray = cmd(I,R),
|
setarray = sp1 * tok.gamearray * arraypat * sp1 * tok.rvar
|
||||||
getarraysize = cmd(I,W),
|
/ "%1[%2]=%3",
|
||||||
readarrayfromfile = cmd(I,D),
|
resizearray = cmd(GARI,R)
|
||||||
writearraytofile = cmd(I,D),
|
/ "%1:resize(%2)",
|
||||||
|
getarraysize = cmd(GARI,W)
|
||||||
|
/ "%2=%1._size",
|
||||||
|
readarrayfromfile = cmd(GARI,D),
|
||||||
|
writearraytofile = cmd(GARI,D),
|
||||||
|
|
||||||
addlogvar = cmd(R)
|
addlogvar = cmd(R)
|
||||||
/ handle.addlogvar,
|
/ handle.addlogvar,
|
||||||
|
@ -2269,7 +2358,6 @@ local function get_deferred_code(tab, lev, code)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function begin_if_fn(condstr, endifstr, endifelsestr)
|
local function begin_if_fn(condstr, endifstr, endifelsestr)
|
||||||
condstr = condstr or "TODO"
|
|
||||||
assert(type(condstr)=="string")
|
assert(type(condstr)=="string")
|
||||||
|
|
||||||
add_deferred_code(g_endIfCode, g_iflevel, endifstr)
|
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
|
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),
|
+ (tok.identifier / function(id) return lookup.gamevar(id, "_aci", true) end),
|
||||||
|
|
||||||
|
t_gamearray = Var("t_identifier") / lookup.gamearray,
|
||||||
|
|
||||||
t_move =
|
t_move =
|
||||||
POS()*tok.identifier / function(...) return lookup.composite(LABEL.MOVE, ...) end +
|
POS()*tok.identifier / function(...) return lookup.composite(LABEL.MOVE, ...) end +
|
||||||
POS()*tok.number / function(...) return check_composite_literal(LABEL.MOVE, ...) end,
|
POS()*tok.number / function(...) return check_composite_literal(LABEL.MOVE, ...) end,
|
||||||
|
|
Loading…
Reference in a new issue