From 27c80248889ff68aa51420f7c9b9dc07957525c5 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Mon, 29 Jan 2018 15:14:39 -0800 Subject: Added numeric-for list comprehension --- lib/class.nom | 104 ---------------------------------------------------- lib/collections.nom | 23 ++++++++++++ lib/object.nom | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+), 104 deletions(-) delete mode 100644 lib/class.nom create mode 100644 lib/object.nom diff --git a/lib/class.nom b/lib/class.nom deleted file mode 100644 index b7506f3..0000000 --- a/lib/class.nom +++ /dev/null @@ -1,104 +0,0 @@ -use "lib/core.nom" - -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 "_me."..key_attr; - elseif key_lua:sub(1,1) == "[" then - key_lua = " "..key_lua.." "; - end - return "_me["..key_lua.."]"; - -compile [@%var <- %val] to code - lua> ".." - local val_lua = \(%val as 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 "_me."..key_attr.." = "..val_lua..";"; - elseif key_lua:sub(1,1) == "[" then - key_lua = " "..key_lua.." "; - end - return "_me["..key_lua.."] = "..val_lua..";"; - -compile [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 'object % %', not \(%line's "src")" - lua> ".." - assert(\%line.value[3].type == "Block", - "Invalid type for action definition body. Expected Block, but got: "..tostring(\%line.value[3].type)); - local names, args = nomsu:parse_spec(\%line.value[2]); - local stub = nomsu:get_stub(names[1]); - local body_lua = nomsu:tree_to_lua(\%line.value[3]); - body_lua = body_lua.statements or ("return "..body_lua.expr..";"); - local arg_nomsus = {}; - for i, arg in ipairs(args) do arg_nomsus[i] = "nomsu:tree_to_lua("..arg..").expr"; end - 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, %s); - ACTION_METADATA[%s[ %s]] = ACTION_METADATA[ACTIONS[ %s]]; - ]==]):format( - \%class_identifier, repr(stub), table.concat(args, ", "), - body_lua, - repr(names), repr(\%line:get_line_no()), table.concat(args, ", "), - repr(repr(stub)), table.concat(arg_nomsus, ".."), - repr(nomsu:dedent(\%line:get_src())), - \%class_identifier, repr(stub), repr(stub))); - - return ".." - do -- \%class_identifier - -- Create the class object: - local \%class_identifier = setmetatable({ - name=\(%classname as lua), 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") - diff --git a/lib/collections.nom b/lib/collections.nom index ac1b019..a2ee0cc 100644 --- a/lib/collections.nom +++ b/lib/collections.nom @@ -75,6 +75,29 @@ immediately end)() parse [%expression for all %iterable] as: %expression for % in %iterable + compile [..] + %expression for %index from %start to %stop via %step + %expression for %index from %start to %stop by %step + ..to + assume ((%index's "type") is "Var") or barf ".." + List comprehension has the wrong type for the loop variable. Expected Var, but got: \(%index's "type") + return {..} + expr:".." + (function() + local comprehension = {}; + for \(%index as lua expr)=\(%start as lua expr),\(%stop as lua expr),\(%step as lua expr) do + comprehension[\(%index as lua expr)] = \(%expression as lua expr); + end + return comprehension; + end)() + parse [%expression for all ] as: %expression for % in %iterable + parse [%expression for %var from %start to %stop] as: %expression for %var from %start to %stop via 1 + parse [..] + %expression for all %start to %stop by %step + %expression for all %start to %stop via %step + ..as: %expression for % from %start to %stop via %step + parse [%expression for all %start to %stop] as: %expression for all %start to %stop via 1 + compile [%expression for %key = %value in %iterable] to assume ((%key's "type") is "Var") or barf ".." List comprehension has the wrong type for the key loop variable. Expected Var, but got: \(%key's "type") diff --git a/lib/object.nom b/lib/object.nom new file mode 100644 index 0000000..b7506f3 --- /dev/null +++ b/lib/object.nom @@ -0,0 +1,104 @@ +use "lib/core.nom" + +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 "_me."..key_attr; + elseif key_lua:sub(1,1) == "[" then + key_lua = " "..key_lua.." "; + end + return "_me["..key_lua.."]"; + +compile [@%var <- %val] to code + lua> ".." + local val_lua = \(%val as 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 "_me."..key_attr.." = "..val_lua..";"; + elseif key_lua:sub(1,1) == "[" then + key_lua = " "..key_lua.." "; + end + return "_me["..key_lua.."] = "..val_lua..";"; + +compile [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 'object % %', not \(%line's "src")" + lua> ".." + assert(\%line.value[3].type == "Block", + "Invalid type for action definition body. Expected Block, but got: "..tostring(\%line.value[3].type)); + local names, args = nomsu:parse_spec(\%line.value[2]); + local stub = nomsu:get_stub(names[1]); + local body_lua = nomsu:tree_to_lua(\%line.value[3]); + body_lua = body_lua.statements or ("return "..body_lua.expr..";"); + local arg_nomsus = {}; + for i, arg in ipairs(args) do arg_nomsus[i] = "nomsu:tree_to_lua("..arg..").expr"; end + 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, %s); + ACTION_METADATA[%s[ %s]] = ACTION_METADATA[ACTIONS[ %s]]; + ]==]):format( + \%class_identifier, repr(stub), table.concat(args, ", "), + body_lua, + repr(names), repr(\%line:get_line_no()), table.concat(args, ", "), + repr(repr(stub)), table.concat(arg_nomsus, ".."), + repr(nomsu:dedent(\%line:get_src())), + \%class_identifier, repr(stub), repr(stub))); + + return ".." + do -- \%class_identifier + -- Create the class object: + local \%class_identifier = setmetatable({ + name=\(%classname as lua), 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") + -- cgit v1.2.3