diff options
Diffstat (limited to 'containers.moon')
| -rw-r--r-- | containers.moon | 87 |
1 files changed, 66 insertions, 21 deletions
diff --git a/containers.moon b/containers.moon index eaf007a..4671f6b 100644 --- a/containers.moon +++ b/containers.moon @@ -1,19 +1,41 @@ -- This file contains container classes, i.e. Lists, Dicts, and Sets {:insert,:remove,:concat} = table -{:repr, :stringify, :equivalent, :nth_to_last, :size} = require 'utils' +{:equivalent, :nth_to_last, :size} = require 'utils' lpeg = require 'lpeg' re = require 're' local List, Dict +as_nomsu = => + if type(@) == 'number' + return tostring(@) + if mt = getmetatable(@) + if _as_nomsu = mt.as_nomsu + return _as_nomsu(@) + return tostring(@) + +as_lua = => + if type(@) == 'number' + return tostring(@) + if mt = getmetatable(@) + if _as_lua = mt.as_lua + return _as_lua(@) + return tostring(@) + -- 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 = + __type: "List" __eq:equivalent -- Could consider adding a __newindex to enforce list-ness, but would hurt performance __tostring: => - "["..concat([repr(b) for b in *@], ", ").."]" + "["..concat([as_nomsu(b) for b in *@], ", ").."]" + as_nomsu: => + "["..concat([as_nomsu(b) for b in *@], ", ").."]" + as_lua: => + "_List{"..concat([as_lua(b) for b in *@], ", ").."}" __lt: (other)=> assert type(@) == 'table' and type(other) == 'table', "Incompatible types for comparison" for i=1,math.max(#@, #other) @@ -36,30 +58,41 @@ _list_mt = 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 + add: insert, append: insert + add_1_at_index: (t,x,i)-> insert(t,i,x) + at_index_1_add: insert + pop: remove, remove_last: remove, remove_index: 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 -- TODO: use stringify() to allow joining misc. objects? joined: => table.concat([tostring(x) for x in *@]), - joined_with_1: (glue)=> table.concat([tostring(x) for x in *@], glue), - has_1: (item)=> + joined_with: (glue)=> table.concat([tostring(x) for x in *@], glue), + has: (item)=> for x in *@ if x == item return true return false - index_of_1: (item)=> + remove: (item)=> + for i,x in ipairs @ + if x == item + remove(@, i) + index_of: (item)=> for i,x in ipairs @ if x == item return i return nil + from_1_to: (start, stop)=> + n = #@ + start = (n+1-start) if n < 0 + stop = (n+1-stop) if n < 0 + return [@[i] for i=start,stop] -- TODO: remove this safety check to get better performance? __newindex: (k,v)=> assert type(k) == 'number', "List indices must be numbers" rawset(@, k, v) +_list_mt.__index.as_lua = _list_mt.as_lua +_list_mt.__index.as_nomsu = _list_mt.as_nomsu List = (t)-> setmetatable(t, _list_mt) @@ -71,10 +104,15 @@ walk_items = (i)=> return i, Dict{key:k, value:v} _dict_mt = + __type: "Dict" __eq:equivalent __len:size __tostring: => - "{"..concat(["#{repr(k)}: #{repr(v)}" for k,v in pairs @], ", ").."}" + "{"..concat(["#{as_nomsu(k)}: #{as_nomsu(v)}" for k,v in pairs @], ", ").."}" + as_nomsu: => + "{"..concat(["#{as_nomsu(k)}: #{as_nomsu(v)}" for k,v in pairs @], ", ").."}" + as_lua: => + "_Dict{"..concat(["[ #{as_lua(k)}]= #{as_lua(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} @@ -109,15 +147,17 @@ for i,entry in ipairs(Dict({x:99})) do {:reverse, :upper, :lower, :find, :byte, :match, :gmatch, :gsub, :sub, :format, :rep} = string string2 = require 'string2' - {:lines, :line, :line_at, :as_lua_id} = string2 + {:lines, :line, :line_at, :as_lua_id, :is_lua_id} = string2 text_methods = - formatted_with_1:format, byte_1:byte, position_of_1:find, position_of_1_after_2:find, - bytes_1_to_2: (start, stop)=> List{byte(tostring(@), start, stop)} - [as_lua_id "with 1 -> 2"]: gsub + formatted_with:format, byte:byte, position_of:find, position_of_1_after:find, + as_a_lua_identifier: as_lua_id, is_a_lua_identifier: is_lua_id, + as_a_lua_id: as_lua_id, is_a_lua_id: is_lua_id, + bytes_1_to: (start, stop)=> List{byte(tostring(@), start, stop)} + [as_lua_id "with 1 ->"]: gsub bytes: => List{byte(tostring(@), 1, -1)}, lines: => List(lines(@)) - line_1: line - wrap_to_1: (maxlen)=> + line: line + wrapped_to: (maxlen)=> _lines = {} for line in *@lines! while #line > maxlen @@ -129,12 +169,14 @@ do _lines[#_lines+1] = line return table.concat(_lines, "\n") - line_at_1: (i)=> (line_at(@, i)) - line_number_of_1: (i)=> select(2, line_at(@, i)) - line_position_of_1: (i)=> select(3, line_at(@, i)) - matches_1: (patt)=> match(@, patt) and true or false + line_at: (i)=> (line_at(@, i)) + line_number_at: (i)=> select(2, line_at(@, i)) + line_position_at: (i)=> select(3, line_at(@, i)) + matches: (patt)=> match(@, patt) and true or false + matching: (patt)=> (match(@, patt)) + matching_groups: (patt)=> {match(@, patt)} [as_lua_id "* 1"]: (n)=> rep(@, n) - matching_1: (patt)=> + all_matches_of: (patt)=> result = {} stepper,x,i = gmatch(@, patt) while true @@ -146,10 +188,13 @@ do setmetatable(text_methods, {__index:string2}) + getmetatable("").__methods = text_methods getmetatable("").__index = (i)=> -- Use [] for accessing text characters, or s[{3,4}] for s:sub(3,4) if type(i) == 'number' then return sub(@, i, i) elseif type(i) == 'table' then return sub(@, i[1], i[2]) else return text_methods[i] + getmetatable("").__add = (x)=> tostring(@)..tostring(x) + return {:List, :Dict} |
