LunaCON: statically check some member assignments with literal numbers.

And issue warnings whenever the assignment would fail (error) at game time.

git-svn-id: https://svn.eduke32.com/eduke32@4195 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2013-12-11 21:23:42 +00:00
parent a7ed1a6fe9
commit 44351528db
3 changed files with 50 additions and 25 deletions

View file

@ -349,12 +349,22 @@ local function S2U(label)
return { s2u(label), label }
end
-- Some literal checker functions (LITERAL_CHECKING).
-- KEEPINSYNC with the actual setter code.
local function litok_gem1(lit)
return (lit >= -1)
end
local function litok_ge0(lit)
return (lit >= 0)
end
local ActorLabels = {
x = SP".x",
y = SP".y",
z = SP".z",
cstat = SP".cstat",
picnum = { SP".picnum", SP":set_picnum(%%s)" },
picnum = { SP".picnum", SP":set_picnum(%%s)", litok_ge0 },
shade = SP".shade",
pal = SP".pal",
clipdist = SP".clipdist",
@ -364,10 +374,10 @@ local ActorLabels = {
yrepeat = SP".yrepeat",
xoffset = SP".xoffset",
yoffset = SP".yoffset",
sectnum = { SP".sectnum", SP":changesect(%%s)" }, -- set: for tsprite
sectnum = { SP".sectnum", SP":changesect(%%s)", litok_ge0 }, -- set: for tsprite
statnum = { SP".statnum" },
ang = SP".ang",
owner = { SP".owner", SP":_set_owner(%%s)" },
owner = { SP".owner", SP":_set_owner(%%s)", litok_ge0 },
xvel = SP".xvel",
yvel = { SP".yvel", SP":_set_yvel(%%s)" }, -- XXX
zvel = SP".zvel",
@ -380,10 +390,11 @@ local ActorLabels = {
-- ActorExtra labels...
htcgg = AC".cgg",
-- XXX: why <0 allowed?
htpicnum = { AC".picnum", AC":set_picnum(%%s)" },
htang = AC".ang",
htextra = AC".extra",
htowner = { AC".owner", AC":set_owner(%%s)" },
htowner = { AC".owner", AC":set_owner(%%s)", litok_ge0 },
htmovflag = AC"._movflag",
httempang = AC".tempang",
htactorstayput = AC".stayputsect", -- NAME
@ -674,7 +685,7 @@ local SectorLabels = {
floorstat = SEC".floorstat",
-- CEILING
ceilingpicnum = { SEC".ceilingpicnum", SEC":set_ceilingpicnum(%%s)" },
ceilingpicnum = { SEC".ceilingpicnum", SEC":set_ceilingpicnum(%%s)", litok_ge0 },
ceilingslope = SEC".ceilingheinum", -- NAME
ceilingshade = SEC".ceilingshade",
@ -684,7 +695,7 @@ local SectorLabels = {
ceilingypanning = SEC".ceilingypanning",
-- FLOOR
floorpicnum = { SEC".floorpicnum", SEC":set_floorpicnum(%%s)" },
floorpicnum = { SEC".floorpicnum", SEC":set_floorpicnum(%%s)", litok_ge0 },
floorslope = SEC".floorheinum", -- NAME
floorshade = SEC".floorshade",
@ -718,8 +729,8 @@ local WallLabels = {
nextwall = { WAL".nextwall", WAL":_set_nextwall(%%s)" },
nextsector = { WAL".nextsector", WAL":_set_nextsector(%%s)" },
cstat = WAL".cstat",
picnum = { WAL".picnum", WAL":set_picnum(%%s)" },
overpicnum = { WAL".overpicnum", WAL":set_overpicnum(%%s)" },
picnum = { WAL".picnum", WAL":set_picnum(%%s)", litok_ge0 },
overpicnum = { WAL".overpicnum", WAL":set_overpicnum(%%s)", litok_ge0 },
shade = WAL".shade",
pal = WAL".pal",
xrepeat = WAL".xrepeat",
@ -751,17 +762,17 @@ local ProjectileLabels = {
hitradius = PROJ".hitradius",
range = PROJ".range",
flashcolor = PROJ".flashcolor",
spawns = { PROJ".spawns", PROJ":set_spawns(%%s)" },
sound = { PROJ".sound", PROJ":set_sound(%%s)" },
isound = { PROJ".isound", PROJ":set_isound(%%s)" },
spawns = { PROJ".spawns", PROJ":set_spawns(%%s)", litok_gem1 },
sound = { PROJ".sound", PROJ":set_sound(%%s)", litok_gem1 },
isound = { PROJ".isound", PROJ":set_isound(%%s)", litok_gem1 },
vel = PROJ".vel",
decal = { PROJ".decal", PROJ":set_decal(%%s)" },
trail = { PROJ".trail", PROJ":set_trail(%%s)" },
decal = { PROJ".decal", PROJ":set_decal(%%s)", litok_gem1 },
trail = { PROJ".trail", PROJ":set_trail(%%s)", litok_gem1 },
tnum = PROJ".tnum",
drop = PROJ".drop",
offset = PROJ".offset",
bounces = PROJ".bounces",
bsound = { PROJ".bsound", PROJ":set_bsound(%%s)" },
bsound = { PROJ".bsound", PROJ":set_bsound(%%s)", litok_gem1 },
toffset = PROJ".toffset",
extra = PROJ".extra",
extra_rand = PROJ".extra_rand",
@ -817,7 +828,7 @@ local UserdefLabels = {
fta_on = UD".fta_on",
god = UDRO".god",
idplayers = UDRO".idplayers",
level_number = { UD".level_number", UD":set_level_number(%%s)" },
level_number = { UD".level_number", UD":set_level_number(%%s)", {0, MAXLEVELS-1} },
levelstats = UD".levelstats",
lockout = UDRO".lockout",
m_player_skill = UDRO".m_player_skill",
@ -835,7 +846,7 @@ local UserdefLabels = {
showallmap = UD".showallmap",
showweapons = UDRO".showweapons",
statusbarscale = UDRO".statusbarscale",
volume_number = { UD".volume_number", UD":set_volume_number(%%s)" },
volume_number = { UD".volume_number", UD":set_volume_number(%%s)", {0, MAXVOLUMES} },
weaponscale = UDRO".weaponscale",
weaponswitch = UD".weaponswitch",
}

View file

@ -655,10 +655,10 @@ from `0` to `255`.
===== `sector` methods
`sec:set_ceilingpicnum(tilenum)`, `sec:set_floorpicnum(tilenum)`::
`sec:set_ceilingpicnum(tilenum)`, {nbsp} `sec:set_floorpicnum(tilenum)`::
Set the tile number of the ceiling or floor.
[[sec_cfz_at]] `sec:ceilingzat(pos)`, `sec:floorzat(pos)`::
[[sec_cfz_at]] `sec:ceilingzat(pos)`, {nbsp} `sec:floorzat(pos)`::
Return the z coordinate of sector `sec`'s ceiling or floor at position `pos`,
which can be anything indexable with the strings `x` and `y`.

View file

@ -1894,8 +1894,15 @@ local function StructAccess(Structname, writep, index, membertab)
return "_MEMBINVALID"
end
-- Function checking a literal number for being OK for assignment to this
-- member. Can also be a table {min, max}. See con_lang.lua, LITERAL_CHECKING.
local lit_ok_func_or_table
if (type(armembcode)=="table") then
-- Read and write accesses differ.
if (writep) then
lit_ok_func_or_table = armembcode[3]
end
armembcode = armembcode[writep and 2 or 1]
if (armembcode==nil) then
errprintf("%s access to %s[].%s is not available",
@ -1947,7 +1954,7 @@ local function StructAccess(Structname, writep, index, membertab)
end
end
return code, ismethod
return code, ismethod, lit_ok_func_or_table
end
function lookup.array_expr(writep, structname, index, membertab)
@ -2020,13 +2027,20 @@ end
local function SetStructCmd(accessfunc, pattern)
local function capfunc(idx, memb, var)
local membercode, ismethod = accessfunc(true, idx, memb)
--[[
local member = memb[1]:lower()
if (type(var)=="number" and var<0 and member:match("picnum")) then
warnprintf("member '.%s' is set to a negative value", member)
-- litok: function or table
local membercode, ismethod, litok = accessfunc(true, idx, memb)
-- Light static checking for literal values being OK for member
-- assignment. LITERAL_CHECKING.
if (type(var)=="number" and litok) then
if (type(litok)=="table" and not (var>=litok[1] and var<=litok[2]) or
type(litok)=="function" and not litok(var)) then
local member = memb[1]:lower()
warnprintf("setting member '.%s' to %d will fail at game time",
member, var)
end
end
--]]
if (ismethod) then
-- METHOD_MEMBER syntax