aboutsummaryrefslogtreecommitdiff
path: root/containers.moon
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2018-08-29 19:38:14 -0700
committerBruce Hill <bitbucket@bruce-hill.com>2018-08-29 19:39:15 -0700
commit4f30e02acb666c52e0254eb9a3bf89a9cabb5e6d (patch)
treebacc6a2baf70c18d3d44db06dc2235ec42edd49f /containers.moon
parentaae5ce31feb482a86d8ef96fb1f104194f26828c (diff)
Handling more compatibility stuff, including Lua 5.4, and a backup for
if openssl module is not found, and moving containers (List/Dict) into their own file, as well as bit operators (and support for __bxor, etc. metamethods in Lua 5.2/LuaJIT)
Diffstat (limited to 'containers.moon')
-rw-r--r--containers.moon99
1 files changed, 99 insertions, 0 deletions
diff --git a/containers.moon b/containers.moon
new file mode 100644
index 0000000..deb5684
--- /dev/null
+++ b/containers.moon
@@ -0,0 +1,99 @@
+-- This file contains container classes, i.e. Lists, Dicts, and Sets
+{:insert,:remove,:concat} = table
+{:repr, :stringify, :equivalent, :nth_to_last, :size} = require 'utils'
+
+local list, dict
+
+-- List and Dict classes to provide basic equality/tostring functionality for the tables
+-- used in Nomsu. This way, they retain a notion of whether they were originally lists or dicts.
+_list_mt =
+ __eq:equivalent
+ -- Could consider adding a __newindex to enforce list-ness, but would hurt performance
+ __tostring: =>
+ "["..concat([repr(b) for b in *@], ", ").."]"
+ __lt: (other)=>
+ assert type(@) == 'table' and type(other) == 'table', "Incompatible types for comparison"
+ for i=1,math.max(#@, #other)
+ if not @[i] and other[i] then return true
+ elseif @[i] and not other[i] then return false
+ elseif @[i] < other[i] then return true
+ elseif @[i] > other[i] then return false
+ return false
+ __le: (other)=>
+ assert type(@) == 'table' and type(other) == 'table', "Incompatible types for comparison"
+ for i=1,math.max(#@, #other)
+ if not @[i] and other[i] then return true
+ elseif @[i] and not other[i] then return false
+ elseif @[i] < other[i] then return true
+ elseif @[i] > other[i] then return false
+ return true
+ __add: (other)=>
+ ret = list[x for x in *@]
+ for x in *other
+ insert(ret, x)
+ return ret
+ __index:
+ add_1: insert, append_1: insert
+ add_1_at_index_2: (t,x,i)-> insert(t,i,x)
+ at_index_1_add_2: insert
+ pop: remove, remove_last: remove, remove_index_1: remove
+ last: (=> @[#@]), first: (=> @[1])
+ _1_st_to_last:nth_to_last, _1_nd_to_last:nth_to_last
+ _1_rd_to_last:nth_to_last, _1_th_to_last:nth_to_last
+ has_1: (item)=>
+ for x in *@
+ if x == item
+ return true
+ return false
+ index_of_1: (item)=>
+ for i,x in ipairs @
+ if x == item
+ return i
+ return nil
+
+list = (t)-> setmetatable(t, _list_mt)
+
+walk_items = (i)=>
+ i = i + 1
+ k, v = next(@table, @key)
+ if k != nil
+ @key = k
+ return i, dict{key:k, value:v}
+
+_dict_mt =
+ __eq:equivalent
+ __len:size
+ __tostring: =>
+ "{"..concat(["#{repr(k)}: #{repr(v)}" for k,v in pairs @], ", ").."}"
+ __ipairs: => walk_items, {table:@, key:nil}, 0
+ __band: (other)=>
+ dict{k,v for k,v in pairs(@) when other[k] != nil}
+ __bor: (other)=>
+ ret = {k,v for k,v in pairs(@)}
+ for k,v in pairs(other)
+ if ret[k] == nil then ret[k] = v
+ return dict(ret)
+ __bxor: (other)=>
+ ret = {k,v for k,v in pairs(@)}
+ for k,v in pairs(other)
+ if ret[k] == nil then ret[k] = v
+ else ret[k] = nil
+ return dict(ret)
+ __add: (other)=>
+ ret = {k,v for k,v in pairs(@)}
+ for k,v in pairs(other)
+ if ret[k] == nil then ret[k] = v
+ else ret[k] += v
+ return dict(ret)
+ __sub: (other)=>
+ ret = {k,v for k,v in pairs(@)}
+ for k,v in pairs(other)
+ if ret[k] == nil then ret[k] = -v
+ else ret[k] -= v
+ return dict(ret)
+dict = (t)-> setmetatable(t, _dict_mt)
+
+for i,entry in ipairs(dict({x:99}))
+ assert(i == 1 and entry.key == "x" and entry.value == 99, "ipairs compatibility issue")
+
+return {:list, :dict}