]> git.lizzy.rs Git - metalua.git/blobdiff - src/lib/metalua/table2.lua
Merge branch 'master' of ssh://git.eclipse.org/gitroot/koneki/org.eclipse.koneki...
[metalua.git] / src / lib / metalua / table2.lua
diff --git a/src/lib/metalua/table2.lua b/src/lib/metalua/table2.lua
deleted file mode 100644 (file)
index 1db3544..0000000
+++ /dev/null
@@ -1,380 +0,0 @@
----------------------------------------------------------------------
-----------------------------------------------------------------------
---
--- Table module extension
---
-----------------------------------------------------------------------
-----------------------------------------------------------------------
-
--- todo: table.scan (scan1?) fold1? flip?
-
-function table.transpose(t)
-   local tt = { }
-   for a, b in pairs(t) do tt[b] = a end
-   return tt
-end
-
-function table.iforeach(f, ...)
-   -- assert (type (f) == "function") [wouldn't allow metamethod __call]
-   local nargs = select("#", ...)
-   if nargs==1 then -- Quick iforeach (most common case), just one table arg
-      local t = ...
-      assert (type (t) == "table")
-      for i = 1, #t do 
-         local result = f (t[i])
-         -- If the function returns non-false, stop iteration
-         if result then return result end
-      end
-   else -- advanced case: boundaries and/or multiple tables
-
-      -- fargs:       arguments fot a single call to f
-      -- first, last: indexes of the first & last elements mapped in each table
-      -- arg1:        index of the first table in args
-
-      -- 1 - find boundaries if any
-      local  args, fargs, first, last, arg1 = {...}, { }
-      if     type(args[1]) ~= "number" then first, arg1 = 1, 1 -- no boundary
-      elseif type(args[2]) ~= "number" then first, last, arg1 = 1, args[1], 2
-      else   first,  last, arg1 = args[1], args[2], 3 end
-      assert (nargs >= arg1) -- at least one table
-      -- 2 - determine upper boundary if not given
-      if not last then for i = arg1, nargs do 
-            assert (type (args[i]) == "table")
-            last = max (#args[i], last) 
-      end end
-      -- 3 - remove non-table arguments from args, adjust nargs
-      if arg1>1 then args = { select(arg1, unpack(args)) }; nargs = #args end
-
-      -- 4 - perform the iteration
-      for i = first, last do
-         for j = 1, nargs do fargs[j] = args[j][i] end -- build args list
-         local result = f (unpack (fargs)) -- here is the call
-         -- If the function returns non-false, stop iteration
-         if result then return result end
-      end
-   end
-end
-
-function table.imap (f, ...)
-   local result, idx = { }, 1
-   local function g(...) result[idx] = f(...);  idx=idx+1 end
-   table.iforeach(g, ...)
-   return result
-end
-
-function table.ifold (f, acc, ...)
-   local function g(...) acc = f (acc,...) end
-   table.iforeach (g, ...)
-   return acc
-end
-
--- function table.ifold1 (f, ...)
---    return table.ifold (f, acc, 2, false, ...)
--- end
-
-function table.izip(...)
-   local function g(...) return {...} end
-   return table.imap(g, ...)
-end
-
-function table.ifilter(f, t)
-   local yes, no = { }, { }
-   for i=1,#t do table.insert (f(t[i]) and yes or no, t[i]) end
-   return yes, no
-end
-
-function table.icat(...)
-   local result = { }
-   for t in values {...} do
-      for x in values (t) do
-         table.insert (result, x)
-      end
-   end
-   return result
-end
-
-function table.iflatten (x) return table.icat (unpack (x)) end
-
-function table.irev (t)
-   local result, nt = { }, #t
-   for i=0, nt-1 do result[nt-i] = t[i+1] end
-   return result
-end
-
-function table.isub (t, ...)
-   local ti, u = table.insert, { }
-   local args, nargs = {...}, select("#", ...)
-   for i=1, nargs/2 do
-      local a, b = args[2*i-1], args[2*i]
-      for i=a, b, a<=b and 1 or -1 do ti(u, t[i]) end
-   end
-   return u
-end
-
-function table.iall (f, ...)
-   local result = true
-   local function g(...) return not f(...) end
-   return not table.iforeach(g, ...)
-   --return result
-end
-
-function table.iany (f, ...)
-   local function g(...) return not f(...) end
-   return not table.iall(g, ...)
-end
-
-function table.shallow_copy(x)
-   local y={ }
-   for k, v in pairs(x) do y[k]=v end
-   return y
-end
-
--- Warning, this is implementation dependent: it relies on
--- the fact the [next()] enumerates the array-part before the hash-part.
-function table.cat(...)
-   local y={ }
-   for x in values{...} do
-      -- cat array-part
-      for _, v in ipairs(x) do table.insert(y,v) end
-      -- cat hash-part
-      local lx, k = #x
-      if lx>0 then k=next(x,lx) else k=next(x) end
-      while k do y[k]=x[k]; k=next(x,k) end
-   end
-   return y
-end
-
-function table.deep_copy(x) 
-   local tracker = { }
-   local function aux (x)
-      if type(x) == "table" then
-         local y=tracker[x]
-         if y then return y end
-         y = { }; tracker[x] = y
-         setmetatable (y, getmetatable (x))
-         for k,v in pairs(x) do y[aux(k)] = aux(v) end
-         return y
-      else return x end
-   end
-   return aux(x)
-end
-
-function table.override(dst, src)
-   for k, v in pairs(src) do dst[k] = v end
-   for i = #src+1, #dst   do dst[i] = nil end
-   return dst
-end
-
-
-function table.range(a,b,c)
-   if not b then assert(not(c)); b=a; a=1
-   elseif not c then c = (b>=a) and 1 or -1 end
-   local result = { }
-   for i=a, b, c do table.insert(result, i) end
-   return result
-end
-
--- FIXME: new_indent seems to be always nil?!
--- FIXME: accumulator function should be configurable,
--- so that print() doesn't need to bufferize the whole string
--- before starting to print.
-function table.tostring(t, ...)
-   local PRINT_HASH, HANDLE_TAG, FIX_INDENT, LINE_MAX, INITIAL_INDENT = true, true
-   for _, x in ipairs {...} do
-      if type(x) == "number" then
-         if not LINE_MAX then LINE_MAX = x
-         else INITIAL_INDENT = x end
-      elseif x=="nohash" then PRINT_HASH = false
-      elseif x=="notag"  then HANDLE_TAG = false
-      else
-         local n = string['match'](x, "^indent%s*(%d*)$")
-         if n then FIX_INDENT = tonumber(n) or 3 end
-      end
-   end
-   LINE_MAX       = LINE_MAX or math.huge
-   INITIAL_INDENT = INITIAL_INDENT or 1
-   
-   local current_offset =  0  -- indentation level
-   local xlen_cache     = { } -- cached results for xlen()
-   local acc_list       = { } -- Generated bits of string
-   local function acc(...)    -- Accumulate a bit of string
-      local x = table.concat{...}
-      current_offset = current_offset + #x
-      table.insert(acc_list, x) 
-   end
-   local function valid_id(x)
-      -- FIXME: we should also reject keywords; but the list of
-      -- current keywords is not fixed in metalua...
-      return type(x) == "string" 
-         and string['match'](x, "^[a-zA-Z_][a-zA-Z0-9_]*$")
-   end
-   
-   -- Compute the number of chars it would require to display the table
-   -- on a single line. Helps to decide whether some carriage returns are
-   -- required. Since the size of each sub-table is required many times,
-   -- it's cached in [xlen_cache].
-   local xlen_type = { }
-   local function xlen(x, nested)
-      nested = nested or { }
-      if x==nil then return #"nil" end
-      --if nested[x] then return #tostring(x) end -- already done in table
-      local len = xlen_cache[x]
-      if len then return len end
-      local f = xlen_type[type(x)]
-      if not f then return #tostring(x) end
-      len = f (x, nested) 
-      xlen_cache[x] = len
-      return len
-   end
-
-   -- optim: no need to compute lengths if I'm not going to use them
-   -- anyway.
-   if LINE_MAX == math.huge then xlen = function() return 0 end end
-
-   xlen_type["nil"] = function () return 3 end
-   function xlen_type.number  (x) return #tostring(x) end
-   function xlen_type.boolean (x) return x and 4 or 5 end
-   function xlen_type.string  (x) return #string.format("%q",x) end
-   function xlen_type.table   (adt, nested)
-
-      -- Circular references detection
-      if nested [adt] then return #tostring(adt) end
-      nested [adt] = true
-
-      local has_tag  = HANDLE_TAG and valid_id(adt.tag)
-      local alen     = #adt
-      local has_arr  = alen>0
-      local has_hash = false
-      local x = 0
-      
-      if PRINT_HASH then
-         -- first pass: count hash-part
-         for k, v in pairs(adt) do
-            if k=="tag" and has_tag then 
-               -- this is the tag -> do nothing!
-            elseif type(k)=="number" and k<=alen and math.fmod(k,1)==0 then 
-               -- array-part pair -> do nothing!
-            else
-               has_hash = true
-               if valid_id(k) then x=x+#k
-               else x = x + xlen (k, nested) + 2 end -- count surrounding brackets
-               x = x + xlen (v, nested) + 5          -- count " = " and ", "
-            end
-         end
-      end
-
-      for i = 1, alen do x = x + xlen (adt[i], nested) + 2 end -- count ", "
-      
-      nested[adt] = false -- No more nested calls
-
-      if not (has_tag or has_arr or has_hash) then return 3 end
-      if has_tag then x=x+#adt.tag+1 end
-      if not (has_arr or has_hash) then return x end
-      if not has_hash and alen==1 and type(adt[1])~="table" then
-         return x-2 -- substract extraneous ", "
-      end
-      return x+2 -- count "{ " and " }", substract extraneous ", "
-   end
-   
-   -- Recursively print a (sub) table at given indentation level.
-   -- [newline] indicates whether newlines should be inserted.
-   local function rec (adt, nested, indent)
-      if not FIX_INDENT then indent = current_offset end
-      local function acc_newline()
-         acc ("\n"); acc (string.rep (" ", indent)) 
-         current_offset = indent
-      end
-      local x = { }
-      x["nil"] = function() acc "nil" end
-      function x.number()   acc (tostring (adt)) end
-      --function x.string()   acc (string.format ("%q", adt)) end
-      function x.string()   acc ((string.format ("%q", adt):gsub("\\\n", "\\n"))) end
-      function x.boolean()  acc (adt and "true" or "false") end
-      function x.table()
-         if nested[adt] then acc(tostring(adt)); return end
-         nested[adt]  = true
-
-
-         local has_tag  = HANDLE_TAG and valid_id(adt.tag)
-         local alen     = #adt
-         local has_arr  = alen>0
-         local has_hash = false
-
-         if has_tag then acc("`"); acc(adt.tag) end
-
-         -- First pass: handle hash-part
-         if PRINT_HASH then
-            for k, v in pairs(adt) do
-               -- pass if the key belongs to the array-part or is the "tag" field
-               if not (k=="tag" and HANDLE_TAG) and 
-                  not (type(k)=="number" and k<=alen and math.fmod(k,1)==0) then
-
-                  -- Is it the first time we parse a hash pair?
-                  if not has_hash then 
-                     acc "{ "
-                     if not FIX_INDENT then indent = current_offset end
-                  else acc ", " end
-
-                  -- Determine whether a newline is required
-                  local is_id, expected_len = valid_id(k)
-                  if is_id then expected_len = #k + xlen (v, nested) + #" = , "
-                  else expected_len = xlen (k, nested) + 
-                                      xlen (v, nested) + #"[] = , " end
-                  if has_hash and expected_len + current_offset > LINE_MAX
-                  then acc_newline() end
-                  
-                  -- Print the key
-                  if is_id then acc(k); acc " = " 
-                  else  acc "["; rec (k, nested, indent+(FIX_INDENT or 0)); acc "] = " end
-
-                  -- Print the value
-                  rec (v, nested, indent+(FIX_INDENT or 0))
-                  has_hash = true
-               end
-            end
-         end
-
-         -- Now we know whether there's a hash-part, an array-part, and a tag.
-         -- Tag and hash-part are already printed if they're present.
-         if not has_tag and not has_hash and not has_arr then acc "{ }"; 
-         elseif has_tag and not has_hash and not has_arr then -- nothing, tag already in acc
-         else 
-            assert (has_hash or has_arr)
-            local no_brace = false
-            if has_hash and has_arr then acc ", " 
-            elseif has_tag and not has_hash and alen==1 and type(adt[1])~="table" then
-               -- No brace required; don't print "{", remember not to print "}"
-               acc (" "); rec (adt[1], nested, indent+(FIX_INDENT or 0))
-               no_brace = true
-            elseif not has_hash then
-               -- Braces required, but not opened by hash-part handler yet
-               acc "{ "
-               if not FIX_INDENT then indent = current_offset end
-            end
-
-            -- 2nd pass: array-part
-            if not no_brace and has_arr then 
-               rec (adt[1], nested, indent+(FIX_INDENT or 0))
-               for i=2, alen do 
-                  acc ", ";                   
-                  if   current_offset + xlen (adt[i], { }) > LINE_MAX
-                  then acc_newline() end
-                  rec (adt[i], nested, indent+(FIX_INDENT or 0)) 
-               end
-            end
-            if not no_brace then acc " }" end
-         end
-         nested[adt] = false -- No more nested calls
-      end
-      local y = x[type(adt)]
-      if y then y() else acc(tostring(adt)) end
-   end
-   --printf("INITIAL_INDENT = %i", INITIAL_INDENT)
-   current_offset = INITIAL_INDENT or 0
-   rec(t, { }, 0)
-   return table.concat (acc_list)
-end
-
-function table.print(...) return print(table.tostring(...)) end
-
-return table
\ No newline at end of file