136 lines
5.8 KiB
Plaintext
136 lines
5.8 KiB
Plaintext
![]() |
use "core"
|
||
|
|
||
|
compile [@] to {expr:"self"}
|
||
|
|
||
|
compile [@%var] to:
|
||
|
lua> ".."
|
||
|
local key_lua = repr(\%var.value);
|
||
|
local key_attr = (key_lua:match("'([a-zA-Z][a-zA-Z0-9]*)'")
|
||
|
or key_lua:match('"([a-zA-Z][a-zA-Z0-9]*)"'));
|
||
|
if key_attr then
|
||
|
return {expr="self."..key_attr};
|
||
|
elseif key_lua:sub(1,1) == "[" then
|
||
|
key_lua = " "..key_lua.." ";
|
||
|
end
|
||
|
return {expr="self["..key_lua.."]"};
|
||
|
|
||
|
compile [@%var <- %val] to:
|
||
|
lua> ".."
|
||
|
local val_lua = \(%val as lua expr);
|
||
|
local key_lua = repr(\%var.value);
|
||
|
local key_attr = (key_lua:match("'([a-zA-Z][a-zA-Z0-9]*)'")
|
||
|
or key_lua:match('"([a-zA-Z][a-zA-Z0-9]*)"'));
|
||
|
if key_attr then
|
||
|
return {statements="self."..key_attr.." = "..val_lua..";"};
|
||
|
elseif key_lua:sub(1,1) == "[" then
|
||
|
key_lua = " "..key_lua.." ";
|
||
|
end
|
||
|
return {statements="self["..key_lua.."] = "..val_lua..";"};
|
||
|
|
||
|
compile [as %instance %body] to:
|
||
|
%body_lua <- (%body as lua)
|
||
|
return {..}
|
||
|
statements: ".."
|
||
|
do
|
||
|
local self = \(%instance as lua expr);
|
||
|
local global_actions = ACTION;
|
||
|
local ACTION = setmetatable({}, {__index=function(_,key)
|
||
|
local method = self[key];
|
||
|
if method then return (function(...) return method(self, ...); end); end
|
||
|
return global_actions[key];
|
||
|
end});
|
||
|
\((%body_lua's "statements") or "\(%body_lua's "expr");")
|
||
|
end
|
||
|
locals: %body_lua's "locals"
|
||
|
|
||
|
compile [define object %classname %class_body] to:
|
||
|
%class_identifier <- (=lua "nomsu:var_to_lua_identifier(\(%classname as value)):sub(2,-1)")
|
||
|
if: %class_identifier is ""
|
||
|
%class_identifier <- "class"
|
||
|
%methods <- []
|
||
|
for %line in (%class_body's "value"):
|
||
|
if: (%line's "type") is "Comment"
|
||
|
do next %line
|
||
|
assume (((%line's "type") == "FunctionCall") and ((%line's "stub") == "action % %"))
|
||
|
..or barf "Only action definitions are supported inside 'define object % %', not \(%line's "src")"
|
||
|
%actions <- (2nd in (%line's "value"))
|
||
|
%body <- (3rd in (%line's "value"))
|
||
|
lua> ".."
|
||
|
local signature = {};
|
||
|
for i, action in ipairs(\%actions.value) do signature[i] = action:get_src(); end
|
||
|
local stubs = nomsu:get_stubs_from_signature(signature);
|
||
|
local stub_args = nomsu:get_args_from_signature(signature);
|
||
|
local arg_set = {};
|
||
|
for i, arg in ipairs(stub_args[1]) do arg_set[arg] = true; end
|
||
|
local body_lua = nomsu:tree_to_lua(\%body);
|
||
|
local body_code = body_lua.statements or ("return "..body_lua.expr..";");
|
||
|
local undeclared_locals = {};
|
||
|
for i, body_local in ipairs(body_lua.locals or {}) do
|
||
|
if not arg_set[body_local] then
|
||
|
table.insert(undeclared_locals, body_local);
|
||
|
end
|
||
|
end
|
||
|
if #undeclared_locals > 0 then
|
||
|
body_code = "local "..table.concat(undeclared_locals, ", ")..";\\n"..body_code;
|
||
|
end
|
||
|
local lua_fn_args = table.concat({"self", unpack(stub_args[1])}, ", ");
|
||
|
local def_tree = nomsu.compilestack[#nomsu.compilestack];
|
||
|
local code_location = ("%s:%s,%s"):format(def_tree.filename, def_tree.start, def_tree.stop);
|
||
|
|
||
|
local compiled_args = {};
|
||
|
for i, arg in ipairs(stub_args[1]) do
|
||
|
compiled_args[i] = "nomsu:tree_to_lua("..arg..").expr";
|
||
|
end
|
||
|
compiled_args = table.concat(compiled_args, "..', '..");
|
||
|
table.insert(\%methods, ([==[
|
||
|
%s[ %s] = function(%s)
|
||
|
%s
|
||
|
end
|
||
|
]==]):format(
|
||
|
\%class_identifier, repr(stubs[1]), lua_fn_args,
|
||
|
body_code));
|
||
|
|
||
|
return {..}
|
||
|
statements:".."
|
||
|
do -- \%class_identifier
|
||
|
-- Create the class object:
|
||
|
local \%class_identifier = setmetatable({
|
||
|
name=\(%classname as lua expr), instances=setmetatable({}, {__mode="k"}),
|
||
|
}, {
|
||
|
__tostring=function(c) return c.name; end,
|
||
|
__call=function(cls, inst)
|
||
|
inst = inst or {};
|
||
|
inst.id = tostring(inst):match('table: (.*)');
|
||
|
setmetatable(inst, cls.instance_metatable);
|
||
|
cls.instances[inst] = true;
|
||
|
if inst['set % up'] then
|
||
|
inst['set % up'](inst);
|
||
|
end
|
||
|
return inst;
|
||
|
end,
|
||
|
});
|
||
|
\%class_identifier.class = \%class_identifier;
|
||
|
|
||
|
-- Define the methods:
|
||
|
\(%methods joined with "\n")
|
||
|
|
||
|
-- Define class methods for instantiating and accessing instances:
|
||
|
\%class_identifier.instance_metatable = {
|
||
|
__index=\%class_identifier,
|
||
|
__tostring=\%class_identifier['% as text'] or function(inst)
|
||
|
return "<"..inst.class.name..": "..inst.id..">";
|
||
|
end,
|
||
|
};
|
||
|
nomsu:define_action("instances of "..\%class_identifier.name, "lib/class.nom", function()
|
||
|
return utils.keys(\%class_identifier.instances);
|
||
|
end, "");
|
||
|
nomsu:define_action("new "..\%class_identifier.name.." %instance", "lib/class.nom", function(_instance)
|
||
|
return \%class_identifier(_instance);
|
||
|
end, "");
|
||
|
nomsu:define_action("new "..\%class_identifier.name, "lib/class.nom", function()
|
||
|
return \%class_identifier({});
|
||
|
end, "");
|
||
|
end -- End of definition of \%class_identifier
|
||
|
\("\n\n")
|
||
|
|