[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: class syntax (was: Re: Making Lua lexically scoped (was: Re: Proper tail recursion))
- From: "Jay Carlson" <nop@...>
- Date: Mon, 30 Jul 2001 22:30:57 -0400
"David Jeske" <jeske@chat.net> writes:
> On Mon, Jul 30, 2001 at 09:29:31AM -0400, Jay Carlson wrote:
> > David Jeske writes:
> >
> > > I would be far happier if I had a mechanism for making my class system
> > > have more bearable syntax. However, I recognize the likely-hood of Lua
> > > ending up with the meta-syntax mechanisms that I think would go so
> > > well with it's meta-language mechanisms is about zero. :)
> >
> > What does your class system look like?
>
> Below is a real example of a class (cut and pasted right out of my
> game project) which inherits from three 'trait/mixin' style base
> classes.
I've written some sugar and rewritten your example. I have no idea whether
you think this is an improvement or not, but I like it better.
> > What help do you need from the syntax?
>
> 1) Personally, I find languages with task-dedicated syntax
> easier to use and read. If you dedicate your life to
> writing ASTs directly by coding in LISP or Scheme you
> may disagree with me. Please just agree to disagree and
> move on to the next email in your inbox.
No, that's John Ramsdell....well, he's gotten better. :-)
> 3) If you forget something or make a syntax mistake inside a
> function deep within the table, the lack of keywords for
> the compiler to get it's bearings sometimes makes the syntax
> errors obtuse.
Yeah, run into that.
> 4) Personally I find the syntax ugly, and hard to read.
Me too.
> > Do you need reader macros, or can you get away with runtime
> > interpretation?
>
> I'm not sure what you mean by runtime interpretation.
Well, I was thinking of leaning on the use of strings and somewhat
reflective features, but I don't have a good example off the top of my head,
so lemme think of one before I get into it.
> I basically want to create new tokens and new BNF elements which fit
> into the expression/statement part of the language and macro evaluate
> into other existing structures of the language. From what I know of
> lisp-reader-macros, this is sort of what they do.
Yeah; I forget where the Dylan macro proposals went, but they might be a
starting point.
My code follows.
Jay
------ First, the sugar
function begin_class(name)
if _class_declaration then
error("class "..name.." began before ".._class_declaration.name.."
ended")
end
_class_declaration = {name=name, table={}}
-- to be really fastidious about namespace, swap stuff like add_slots_to
into globals() now
-- if not, feel free to set the global "class" to this so the user
doesn't have to
return _class_declaration.table
end
function add_slots_to(t)
if getn(t) ~= 1 then
error("add_slots_to must have one and only one numeric argument")
end
local target = t[1]
for i,v in t do
if i ~= 1 then
-- if target[i] then error("redefinition of slot") end
target[i] = v
end
end
end
function end_class(name)
if not _class_declaration then
error("end_class without a begin_class")
end
if _class_declaration.name ~= name then
error("end_class of "..name.." but the class
".._class_declaration.name.." is open")
end
declare_class(name, _class_declaration.table)
-- clean anything out of the global namespace that you put there
return nil -- to empty out the "class" global
end
function call_me_before_main_loop()
if _class_declaration then
error("class declaration ".._class_declaration.name.." was never
closed!")
end
end
--- Your code begins here
class = begin_class("MainShip")
add_slots_to{class;
_parents = { air_physics, controllable, collidable },
Condition = "Healthy",
imgdir = 2.0, -- the image index
rimgdir = 1.0,
direction = 0.0, -- in degrees
bullet_type = "bullet",
objtype = "mainship",
exp_timer = 0.0,
frame_time = 70,
layer = 1,
damage = 0,
damage_max = 10,
recharge_rate = 0.1,
VisualRep = VisualReps.newDropShip
}
-- dummy ai_event
function class:ai_event()
end
function class:new(a_list) -- constructor
if (type(a_list) ~= "table") then
print("mainship:new() called with non-table "..tostring(a_list));
else
a_list._parents = { self };
a_list.key = {}; -- make our private keydown list
a_list.ctrl_centered = 1.0;
a_list.dest_dir = 0.0;
end
return a_list
end
function class:recharge(byWhom) -- recharge method
local damage = self.damage;
if (damage > 0) then
damage = max(0,damage - recharge_rate);
self.damage = damage;
end
end
class = end_class("MainShip")
-- [Time passes...]
call_me_before_main_loop()