1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
use "core"
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="_me."..key_attr};
elseif key_lua:sub(1,1) == "[" then
key_lua = " "..key_lua.." ";
end
return {expr="_me["..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="_me."..key_attr.." = "..val_lua..";"};
elseif key_lua:sub(1,1) == "[" then
key_lua = " "..key_lua.." ";
end
return {statements="_me["..key_lua.."] = "..val_lua..";"};
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 stubs = {};
for i, action in ipairs(\%actions.value) do
stubs[i] = nomsu:tree_to_named_stub(action);
end
local args = {};
for i,tok in ipairs(\%actions.value[1].value) do
if tok.type == "Var" then args[#args+1] = nomsu:var_to_lua_identifier(tok.value); end
end
local arg_set = {};
for i, arg in ipairs(args) 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(args, ", ");
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(args) 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
nomsu:define_compile_action(%s, %s, function(%s)
return {expr="("..nomsu:tree_to_lua(_me).expr..")[ "..%s.."]("..%s..")"};
end);
ACTION_METADATA[%s[ %s]] = ACTION_METADATA[ACTION[ %s]];
]==]):format(
\%class_identifier, repr(stubs[1]), lua_fn_args,
body_code,
repr(stubs), repr(code_location), lua_fn_args,
repr(repr(stubs[1])), compiled_args,
\%class_identifier, repr(stubs[1]), repr(stubs[1])));
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")
|