Lunatic translator: codegen for some "method-like" member write accesses.

git-svn-id: https://svn.eduke32.com/eduke32@3444 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2013-02-01 13:04:52 +00:00
parent 8d64c001a0
commit f95b6fddb5
5 changed files with 79 additions and 18 deletions

View file

@ -421,8 +421,9 @@ local PlayerLabels = {
max_actors_killed = PL".max_actors_killed",
actors_killed = PL".actors_killed",
-- NOTE the special case:
gotweapon = { "("..PL":have_weapon(%s) and 1 or 0)" },
-- NOTE the special case; "%%s" is used to mark settable members
-- with METHOD_MEMBER syntax, it's the value to be set.
gotweapon = { "("..PL":have_weapon(%s) and 1 or 0)", PL":_gt_weapon(%s,%%s)" },
zoom = PL".zoom",
loogiex = {},
@ -511,7 +512,7 @@ local PlayerLabels = {
return_to_center = PL".return_to_center",
reloading = PL".reloading",
weapreccnt = PL".weapreccnt",
weapreccnt = { PL".weapreccnt" },
aim_mode = PL".aim_mode",
auto_aim = PL".auto_aim",
@ -573,13 +574,13 @@ local PlayerLabels = {
weapon_pos = PL".weapon_pos",
wantweaponfire = PL".wantweaponfire",
curr_weapon = { PL".curr_weapon" },
curr_weapon = { PL".curr_weapon", PL":set_curr_weapon(%%s)" },
palette = PL".palette",
-- NOTE the special case:
pals = {},
pals_time = PL".pals.f",
pals = PL"._pals[%s]",
pals_time = PL"._pals.f",
name = {},

View file

@ -215,7 +215,8 @@ local DUKEPLAYER_STRUCT = [[
uint8_t max_secret_rooms, secret_rooms;
uint8_t frag, fraggedself, quick_kick, last_quick_kick;
uint8_t return_to_center, reloading, weapreccnt;
uint8_t return_to_center, reloading;
const uint8_t weapreccnt;
uint8_t aim_mode, auto_aim, weaponswitch, movement_lock, team;
uint8_t tipincs, hbomb_hold_delay, frag_ps, kickback_pic;
@ -237,7 +238,7 @@ local DUKEPLAYER_STRUCT = [[
const int8_t curr_weapon;
uint8_t palette;
palette_t pals;
palette_t _pals;
const char name[32];
@ -833,6 +834,7 @@ local player_mt = {
end,
set_curr_weapon = function(p, weap)
check_weapon_idx(weap)
p.curr_weapon = weap
end,
@ -862,6 +864,23 @@ local player_mt = {
return (bit.band(p.gotweapon, bit.lshift(1, weap)) ~= 0)
end,
give_weapon = function(p, weap)
p.gotweapon = bit.bor(p.gotweapon, bit.lshift(1, weap))
end,
take_weapon = function(p, weap)
p.gotweapon = bit.band(p.gotweapon, bit.bnot(bit.lshift(1, weap)))
end,
-- Give or take weapon, for implementation of CON's .gotweapon access.
_gt_weapon = function(p, weap, give_p)
if (give_p ~= 0) then
p:give_weapon(weap)
else
p:take_weapon(weap)
end
end,
-- XXX: is the correct spelling "whack"?
wack = function(p, no_return_to_center)
p.horiz = p.horiz + 64
@ -875,8 +894,9 @@ local player_mt = {
--- Not fully specified, off-limits to users. Might disappear, change
--- signature, etc...
-- TODO: need to think about external API: 0-255 based? 0-1 based?
_palfrom = function(p, f, r,g,b)
local pals = p.pals
local pals = p._pals
pals.f = f
pals.r, pals.g, pals.b = r, g, b
end,

View file

@ -12,8 +12,10 @@ ffi.cdef "enum { _DEBUG_LUNATIC=1 }"
local bit = require("bit")
local string = require("string")
local assert = assert
local error = error
local pairs = pairs
local require = require
local setmetatable = setmetatable
local tostring = tostring
@ -125,13 +127,21 @@ typedef struct {
vec3_t pos;
int16_t sprite, wall, sect;
} hitdata_t;
typedef struct {
unsigned char r,g,b,f;
} palette_t;
#pragma pack(pop)
]])
-- Define the "palette_t" type, which for us has .{r,g,b} fields and a
-- bound-checking array of length 3 overlaid.
-- TODO: bcarray really should allow to simply declare the struct with
-- passed member names instead of "hidden" ones... because wrapping it
-- in a union like this is doing things inside-out really.
local rgbarray_t = require("bcarray").new("uint8_t", 3, "RGB array")
ffi.cdef("typedef union { \
struct { uint8_t r, g, b, f; }; \
$ col; \
} palette_t", rgbarray_t)
assert(ffi.alignof("palette_t")==1)
local vec3_ct = ffi.typeof("vec3_t")
local hitdata_ct = ffi.typeof("hitdata_t")

View file

@ -1141,7 +1141,8 @@ local function StructAccess(Structname, writep, index, membertab)
end
end
local _, numparms = armembcode:gsub("%%s", "%%s", 2)
-- Count number of parameters ("%s"), don't count "%%s".
local _, numparms = armembcode:gsub("[^%%]%%s", "", 2)
if (#membertab ~= numparms) then
local nums = { "one", "two" }
errprintf("%s[].%s has %s parameter%s, but %s given", Structname,
@ -1150,7 +1151,10 @@ local function StructAccess(Structname, writep, index, membertab)
return "_MEMBINVPARM"
end
return format(armembcode, index, parm2)
-- METHOD_MEMBER
local ismethod = (armembcode:find("%%s",1,true)~=nil)
-- If ismethod is true, then the formatted string will now have an "%s"
return format(armembcode, index, parm2), ismethod
end
@ -1160,7 +1164,11 @@ function lookup.array_expr(writep, structname, index, membertab)
return "_NYI"
end
return StructAccess(structname, writep, index, membertab)
local membercode, ismethod = StructAccess(structname, writep, index, membertab)
-- Written METHOD_MEMBER syntax not supported as "qwe:method(asd) = val"
-- isn't valid Lua syntax.
assert(not (writep and ismethod))
return membercode
end
local Access =
@ -1180,7 +1188,20 @@ end
local function SetStructCmd(accessfunc)
local pattern = setstructcmd / function(idx, memb, var)
return format("%s=%s", accessfunc(true, idx, memb), var)
local membercode, ismethod = accessfunc(true, idx, memb)
if (ismethod) then
-- METHOD_MEMBER syntax
-- BE EXTRA CAREFUL! We must be sure that percent characters have
-- not been smuggled into the member code string via variable names
-- etc.
local _, numpercents = membercode:gsub("%%", "", 2)
assert(numpercents==1)
return format(membercode, var)
else
return format("%s=%s", membercode, var)
end
end
return pattern
end

View file

@ -210,6 +210,12 @@ gameevent("JUMP",
ps.pipebombControl = 2
ps.tripbombControl = 2
-- Test of INTERNAL member _pals.
-- NOTE: setting colors partially is bad! E.g. after an item is
-- picked up, col[0] and col[1] remain and tint everything greenish.
ps._pals.col[2] = 20
ps._pals.f = 30
end
)
@ -250,7 +256,10 @@ gameevent(gv.EVENT_ENTERLEVEL,
printf("sqrt(0xffffffff) = %f(ksqrt) %f(math.sqrt)",
gv.ksqrt(0xffffffff), math.sqrt(0xffffffff))
player[0].max_ammo_amount[gv.RPG_WEAPON] = 17
local pl = player[0]
pl.max_ammo_amount[gv.RPG_WEAPON] = 17
pl:give_weapon(gv.RPG_WEAPON)
pl.ammo_amount[gv.RPG_WEAPON] = 54
checkfail("gameevent('GAME', function() print('qwe') end)",
"must be called from top level")