diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2019-03-09 15:53:14 -0800 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2019-03-09 15:53:35 -0800 |
| commit | 0ba6b3e5f64f66ea207c1f1c4035960cff583dbd (patch) | |
| tree | 69c3741ebf608cf816be7254f5a1f73b4c089abd | |
| parent | cac9b2139fd02dacbf0df9d503f8a761f0d953c0 (diff) | |
Added support for coroutines in constructors, as well as multi-argument
constructors.
| -rw-r--r-- | containers.lua | 117 | ||||
| -rw-r--r-- | containers.moon | 62 |
2 files changed, 148 insertions, 31 deletions
diff --git a/containers.lua b/containers.lua index 365fa4d..8d77919 100644 --- a/containers.lua +++ b/containers.lua @@ -1,4 +1,4 @@ -local List, Dict, Undict, _undict_mt, _dict_mt +local List, Dict, Undict, DictEntries, _undict_mt, _dict_mt, _dict_entries_mt local insert, remove, concat do local _obj_0 = table @@ -311,11 +311,12 @@ local _list_mt = { } _list_mt.__index.as_lua = _list_mt.as_lua _list_mt.__index.as_nomsu = _list_mt.as_nomsu -List = function(t) +List = function(t, ...) + local l if type(t) == 'table' then - return setmetatable(t, _list_mt) + l = setmetatable(t, _list_mt) elseif type(t) == 'function' then - local l = setmetatable({ }, _list_mt) + l = setmetatable({ }, _list_mt) local add add = function(...) for i = 1, select('#', ...) do @@ -323,10 +324,22 @@ List = function(t) end end t(add) - return l + elseif type(t) == 'thread' then + l = setmetatable({ }, _list_mt) + for val in coroutine.wrap(t) do + l[#l + 1] = val + end else - return error("Unsupported List type: " .. type(t)) + error("Unsupported List type: " .. type(t)) + end + if select(1, ...) then + local _list_0 = List(...) + for _index_0 = 1, #_list_0 do + local x = _list_0[_index_0] + l[#l + 1] = x + end end + return l end local compliments = setmetatable({ }, { __mode = 'k' @@ -413,6 +426,62 @@ Undict = function(d) end)()) return u end +local _dict_entries_mt +_dict_entries_mt = { + __type = "a Dict's Entries", + __index = function(self, k) + if type(k) == 'number' then + if k == 0 then + return nil + end + if k < 0 then + if k < 0 then + k = #self.dict + k + 1 + end + end + local i, last_k = self._last_i, self._last_k + if k < i then + i, last_k = 0, nil + end + local d = self.dict + for i = i + 1, k do + last_k = next(d, last_k) + if last_k == nil then + return nil + end + end + self._last_i, self._last_k = k, last_k + return Dict({ + key = last_k, + d[last_k] + }) + else + return _dict_entries_mt[k] + end + end, + __len = function(self) + return #self.dict + end, + __eq = function(self, other) + return type(other) == type(self) and getmetatable(other) == getmetatable(self) and other.dict == self.dict + end, + __tostring = function(self) + return "(entries in " .. tostring(self.dict) .. ")" + end, + as_nomsu = function(self) + return "(entries in " .. _dict_mt.as_nomsu(self.dict) .. ")" + end, + as_lua = function(self) + return "entries_in" .. _dict_mt.as_lua(self.dict) + end +} +DictEntries = function(d) + return setmetatable({ + dict = d, + _last_i = 0, + _last_k = nil + }, _dict_entries_mt) +end _dict_mt = { __type = "a Dict", __eq = function(self, other) @@ -471,16 +540,8 @@ _dict_mt = { return _accum_0 end)(), ", ") .. "}" end, - as_list = function(self) - return List((function() - local _accum_0 = { } - local _len_0 = 1 - for k, v in pairs(self) do - _accum_0[_len_0] = k - _len_0 = _len_0 + 1 - end - return _accum_0 - end)()) + as_iterable = function(self) + return DictEntries(self) end, __band = function(self, other) return Dict((function() @@ -567,11 +628,12 @@ _dict_mt = { return ret end } -Dict = function(t) +Dict = function(t, more, ...) + local d if type(t) == 'table' then - return setmetatable(t, _dict_mt) + d = setmetatable(t, _dict_mt) elseif type(t) == 'function' then - local d = setmetatable({ }, _dict_mt) + d = setmetatable({ }, _dict_mt) local add add = function(...) for i = 1, select('#', ...) do @@ -583,12 +645,23 @@ Dict = function(t) d[k] = v end t(add, add_1_eq_2) - return d + elseif type(t) == 'thread' then + d = setmetatable({ }, _dict_mt) + for k, v in coroutine.wrap(t) do + d[k] = v + end else - return error("Unsupported Dict type: " .. type(t)) + error("Unsupported Dict type: " .. type(t)) + end + if more then + for k, v in pairs(Dict(more, ...)) do + d[k] = v + end end + return d end return { List = List, - Dict = Dict + Dict = Dict, + DictEntries = DictEntries } diff --git a/containers.moon b/containers.moon index 8bca1c4..312f783 100644 --- a/containers.moon +++ b/containers.moon @@ -1,5 +1,5 @@ -- This file contains container classes, i.e. Lists and Dicts, plus some extended string functionality -local List, Dict, Undict, _undict_mt, _dict_mt +local List, Dict, Undict, DictEntries, _undict_mt, _dict_mt, _dict_entries_mt {:insert,:remove,:concat} = table as_nomsu = => @@ -134,16 +134,24 @@ _list_mt = _list_mt.__index.as_lua = _list_mt.as_lua _list_mt.__index.as_nomsu = _list_mt.as_nomsu -List = (t)-> +List = (t,...)-> + local l if type(t) == 'table' - return setmetatable(t, _list_mt) + l = setmetatable(t, _list_mt) elseif type(t) == 'function' l = setmetatable({}, _list_mt) add = (...)-> for i=1,select('#',...) do l[#l+1] = select(i,...) t(add) - return l + elseif type(t) == 'thread' + l = setmetatable({}, _list_mt) + for val in coroutine.wrap(t) + l[#l+1] = val else error("Unsupported List type: "..type(t)) + if select(1,...) + for x in *List(...) + l[#l+1] = x + return l compliments = setmetatable({}, {__mode:'k'}) @@ -191,6 +199,34 @@ Undict = (d)-> compliments[u] = Dict{k,true for k,v in pairs(d) when v} return u +local _dict_entries_mt +_dict_entries_mt = + __type: "a Dict's Entries" + __index: (k)=> + if type(k) == 'number' + return nil if k == 0 + if k < 0 then k = #@dict+k+1 if k < 0 + i, last_k = @_last_i, @_last_k + if k < i + i, last_k = 0, nil + d = @dict + for i=i+1,k + last_k = next(d, last_k) + return nil if last_k == nil + @_last_i, @_last_k = k, last_k + return Dict{key:last_k, d[last_k]} + else + return _dict_entries_mt[k] + __len: => #@dict + __eq: (other)=> + type(other) == type(@) and getmetatable(other) == getmetatable(@) and other.dict == @dict + __tostring: => "(entries in "..tostring(@dict)..")" + as_nomsu: => "(entries in ".._dict_mt.as_nomsu(@dict)..")" + as_lua: => "entries_in".._dict_mt.as_lua(@dict) + +DictEntries = (d)-> + setmetatable {dict:d, _last_i:0, _last_k:nil}, _dict_entries_mt + _dict_mt = __type: "a Dict" __eq: (other)=> @@ -211,7 +247,7 @@ _dict_mt = "{"..concat([v == true and "."..as_nomsu(k) or ".#{as_nomsu(k)} = #{as_nomsu(v)}" for k,v in pairs @], ", ").."}" as_lua: => "a_Dict{"..concat(["[ #{as_lua(k)}]= #{as_lua(v)}" for k,v in pairs @], ", ").."}" - as_list: => List[k for k,v in pairs(@)] + as_iterable: => DictEntries(@) __band: (other)=> Dict{k,v for k,v in pairs(@) when other[k]} __bor: (other)=> @@ -244,16 +280,24 @@ _dict_mt = else ret[k] -= v return ret -Dict = (t)-> +Dict = (t,more,...)-> + local d if type(t) == 'table' - return setmetatable(t, _dict_mt) + d = setmetatable(t, _dict_mt) elseif type(t) == 'function' d = setmetatable({}, _dict_mt) add = (...)-> for i=1,select('#',...) do d[select(i,...)] = true add_1_eq_2 = (k, v)-> d[k] = v t(add, add_1_eq_2) - return d + elseif type(t) == 'thread' + d = setmetatable({}, _dict_mt) + for k,v in coroutine.wrap(t) + d[k] = v else error("Unsupported Dict type: "..type(t)) + if more + for k,v in pairs(Dict(more,...)) + d[k] = v + return d -return {:List, :Dict} +return {:List, :Dict, :DictEntries} |
