aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2019-03-09 15:53:14 -0800
committerBruce Hill <bruce@bruce-hill.com>2019-03-09 15:53:35 -0800
commit0ba6b3e5f64f66ea207c1f1c4035960cff583dbd (patch)
tree69c3741ebf608cf816be7254f5a1f73b4c089abd
parentcac9b2139fd02dacbf0df9d503f8a761f0d953c0 (diff)
Added support for coroutines in constructors, as well as multi-argument
constructors.
-rw-r--r--containers.lua117
-rw-r--r--containers.moon62
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}