nomsu/lib/object.nom

137 lines
5.7 KiB
Plaintext
Raw Normal View History

use "core"
compile [@, me] to: Lua value "self"
compile [as %instance %body] to
Lua ".."
do
local self = \(%instance as lua expr);
local global_actions = ACTIONS;
local ACTIONS = setmetatable({}, {__index=function(_,key)
local method = self[key];
if method then return (function(...) return method(self, ...); end); end
return global_actions[key];
end});
\(%body as lua statements)
end
compile [object %classname %class_body] to
2018-05-30 13:46:40 -07:00
%class_id <- (=lua "string.as_lua_id(\(%classname as value)):sub(2,-1)")
if: %class_id is ""
%class_id <- "class"
%methods <-: Lua ""
%__index <- %class_id
%__newindex <- "nil"
2018-05-26 15:04:31 -07:00
for %line in %class_body.value
if: %line.type is "Comment"
do next %line
if: (%line.type is "Action") and ((%line's stub) is "slots %")
%slot_index_clauses <- []
%slot_newindex_clauses <- []
2018-05-26 15:04:31 -07:00
%slots <- %line.value.2
for %slot_index = %slot_var in %slots.value
to %slot_index_clauses add ".."
if key == \(repr %slot_var.value) or key == \(repr (%slot_var as lua expr)) then
return rawget(self, \%slot_index);
end
to %slot_newindex_clauses add ".."
if key == \(repr %slot_var.value) or key == \(repr (%slot_var as lua expr)) or key == \%slot_index then
rawset(self, \%slot_index, value);
end
%__index <- ".."
function(self, key)
\(%slot_index_clauses joined with "\n")
return \%class_id[key];
end
%__newindex <- ".."
function(self, key, value)
\(%slot_newindex_clauses joined with "\n")
error("Attempt to store data in "..repr(key)..", which is not a valid slot on "..tostring(self.class));
end
2018-01-19 17:31:54 -08:00
do next %line
assume ((%line.type is "Action") and ((%line's stub) is "action % %"))
..or barf "Only action definitions are supported inside 'object % %'"
2018-05-26 15:04:31 -07:00
%actions <- %line.value.2
%body <- %line.value.3
lua> ".."
do
local stubs = {}
2018-05-26 15:04:31 -07:00
for i, action in ipairs(\%actions.value) do
stubs[i] = action:get_stub(true)
end
2018-05-26 15:04:31 -07:00
local lua = Lua(\(%line.source), \%class_id, "[ ", repr(stubs[1]), "] = function(self")
local args = {}
for i,tok in ipairs(\%actions[1]) do
if tok.type == "Var" then args[#args+1] = tok end
end
for i, arg in ipairs(args) do
lua:append(", ", nomsu:tree_to_lua(arg))
end
local body_lua = nomsu:tree_to_lua(\%body):as_statements("return ")
body_lua:remove_free_vars(args)
body_lua:declare_locals()
lua:append(")\n ", body_lua, "\nend;\n")
\%methods:append(lua)
end
return
Lua ".."
do -- \%class_id
-- Create the class object
local \%class_id = setmetatable({
name=\(%classname as lua expr), instances=setmetatable({}, {__mode="k"}),
}, {
__tostring=function(c) return c.name; end,
__call=function(cls, initial_values)
local inst = setmetatable({}, cls.instance_metatable);
for k,v in pairs(initial_values) do inst[k] = v; end
cls.instances[inst] = true;
if inst['set % up'] then
inst['set % up'](inst);
end
return inst;
end,
});
\%class_id.class = \%class_id;
-- Define the methods
\%methods
-- Define class methods for instantiating and accessing instances
\%class_id.instance_metatable = {
__index=\%__index,
__newindex=\%__newindex,
__tostring=\%class_id['as text'] or function(inst)
return "<"..inst.class.name..": "..nomsu.ids[inst]..">";
end,
__len=\%class_id['size of'],
__unm=\%class_id['-'],
__add=\%class_id['+ %'],
__sub=\%class_id['- %'],
__mul=\%class_id['* %'],
__div=\%class_id['/ %'],
__mod=\%class_id['wrapped around %'],
__pow=\%class_id['^ %'],
__band=\%class_id['AND %'],
__bor=\%class_id['OR %'],
__bxor=\%class_id['XOR %'],
__bshl=\%class_id['<< %'],
__bshr=\%class_id['>> %'],
__eq=\%class_id['= %'],
__lt=\%class_id['< %'],
__le=\%class_id['<= %'],
};
nomsu:define_action("instances of "..\%class_id.name, function()
return utils.keys(\%class_id.instances);
end);
nomsu:define_action("new "..\%class_id.name.." %instance", function(_instance)
return \%class_id(_instance);
end);
nomsu:define_action("new "..\%class_id.name, function()
return \%class_id({});
end);
end -- End of definition of \%class_id
\("\n\n")