From 2e345e271f27147051b8ce1f2981ba728b14394a Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Thu, 24 May 2018 14:57:24 -0700 Subject: Misc changes, fixed up Object lib and tests. --- lib/object.nom | 206 +++++++++++++++++++++++++++++--------------------------- lib/object2.nom | 175 ----------------------------------------------- 2 files changed, 107 insertions(+), 274 deletions(-) delete mode 100644 lib/object2.nom (limited to 'lib') diff --git a/lib/object.nom b/lib/object.nom index 0bb2538..5c73046 100644 --- a/lib/object.nom +++ b/lib/object.nom @@ -1,100 +1,91 @@ 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 [@, me] to: Lua value "self" -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.." "; +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 - 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" +compile [object %classname %class_body] to + %class_id <- (=lua "Var(\(%classname as value)):as_lua_id():sub(2,-1)") + if: %class_id is "" + %class_id <- "class" + %methods <-: Lua "" + %__index <- %class_id + %__newindex <- "nil" + for %line in %class_body + 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 <- [] + %slots <- %line.2 + for %slot_index = %slot_var in %slots + 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 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")) + assume ((%line.type is "Action") and ((%line's stub) is "action % %")) + ..or barf "Only action definitions are supported inside 'object % %'" + %actions <- %line.2 + %body <- %line.3 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); + do + local stubs = {} + for i, action in ipairs(\%actions) do + stubs[i] = action:get_stub(true) 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 + local lua = Lua(nil, \%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 - 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]))); + 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 {..} - statements:".." - do -- \%class_identifier + return + Lua ".." + do -- \%class_id -- Create the class object - local \%class_identifier = setmetatable({ + local \%class_id = 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); + __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); @@ -102,27 +93,44 @@ compile [define object %classname %class_body] to return inst; end, }); - \%class_identifier.class = \%class_identifier; + \%class_id.class = \%class_id; -- Define the methods - \(%methods joined with "\n") + \%methods -- 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..">"; + \%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_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 + 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") diff --git a/lib/object2.nom b/lib/object2.nom deleted file mode 100644 index 3916fa2..0000000 --- a/lib/object2.nom +++ /dev/null @@ -1,175 +0,0 @@ -use "core" - -compile [@] to: Lua value "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 Lua.value(tree.source, "self."..key_attr); - elseif key_lua:sub(1,1) == "[" then - key_lua = " "..key_lua; - end - return Lua.Value(tree.source, "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 Lua(tree.source, "self.", key_attr, " = ", val_lua, ";"); - elseif key_lua:sub(1,1) == "[" then - key_lua = " "..key_lua.." "; - end - return Lua(tree.source, "self[", key_lua, "] = ", val_lua, ";"); - -compile [as %instance %body] to - %body_lua <- (%body as lua) - lua> "\%body_lua:convert_to_statements();" - return - 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_lua - end - -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 <- [] - %__index <- %class_identifier - %__newindex <- "nil" - for %line in (%class_body's "value") - if: (%line's "type") is "Comment" - do next %line - if: ((%line's "type") is "FunctionCall") and ((%line's stub) is "slots %") - %slot_index_clauses <- [] - %slot_newindex_clauses <- [] - %slots <- %line.value.2.value - for %slot_index = %slot_var in %slots - to %slot_index_clauses add ".." - if key == \(repr (%slot_var's "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's "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_identifier[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 - do next %line - assume ((%line.type is "FunctionCall") and ((%line's stub) is "action % %")) - ..or barf "Only action definitions are supported inside 'define object % %', not \(%line's "src")" - %actions <- %line.value.2 - %body <- %line.value.3 - lua> ".." - do - 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); - body_lua:convert_to_statements(); - body_lua:declare_locals(); - local lua_fn_args = table.concat({"self", unpack(args)}, ", "); - local def_tree = nomsu.compilestack[#nomsu.compilestack]; - - local compiled_args = {}; - for i, arg in ipairs(args) do - compiled_args[i] = "nomsu:tree_to_lua("..arg..")"; - 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_lua)); - end - - return - Lua ".." - 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, 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_identifier.class = \%class_identifier; - - -- Define the methods - \(%methods joined with "\n") - - -- Define class methods for instantiating and accessing instances - \%class_identifier.instance_metatable = { - __index=\%__index, - __newindex=\%__newindex, - __tostring=\%class_identifier['as text'] or function(inst) - return "<"..inst.class.name..": "..nomsu.ids[inst]..">"; - end, - __len=\%class_identifier['size of'], - __unm=\%class_identifier['-'], - __add=\%class_identifier['+ %'], - __sub=\%class_identifier['- %'], - __mul=\%class_identifier['* %'], - __div=\%class_identifier['/ %'], - __mod=\%class_identifier['wrapped around %'], - __pow=\%class_identifier['^ %'], - __band=\%class_identifier['AND %'], - __bor=\%class_identifier['OR %'], - __bxor=\%class_identifier['XOR %'], - __bshl=\%class_identifier['<< %'], - __bshr=\%class_identifier['>> %'], - __eq=\%class_identifier['= %'], - __lt=\%class_identifier['< %'], - __le=\%class_identifier['<= %'], - }; - nomsu:define_action("instances of "..\%class_identifier.name, "lib/class.nom", function(__callsite) - return utils.keys(\%class_identifier.instances); - end, ""); - nomsu:define_action("new "..\%class_identifier.name.." %instance", "lib/class.nom", function(__callsite, _instance) - return \%class_identifier(_instance); - end, ""); - nomsu:define_action("new "..\%class_identifier.name, "lib/class.nom", function(__callsite) - return \%class_identifier({}); - end, ""); - end -- End of definition of \%class_identifier - \("\n\n") - -- cgit v1.2.3