Current File : //usr/share/texlive/texmf-dist/tex/luatex/lualibs/lualibs-util-sta.lua |
if not modules then modules = { } end modules ['util-sta'] = {
version = 1.001,
comment = "companion to util-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
}
local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
local format = string.format
local select, tostring = select, tostring
local trace_stacker = false trackers.register("stacker.resolve", function(v) trace_stacker = v end)
local stacker = stacker or { }
utilities.stacker = stacker
local function start(s,t,first,last)
if s.mode == "switch" then
local n = tostring(t[last])
if trace_stacker then
s.report("start: %s",n)
end
return n
else
local r = { }
for i=first,last do
r[#r+1] = tostring(t[i])
end
local n = concat(r," ")
if trace_stacker then
s.report("start: %s",n)
end
return n
end
end
local function stop(s,t,first,last)
if s.mode == "switch" then
local n = tostring(false)
if trace_stacker then
s.report("stop: %s",n)
end
return n
else
local r = { }
for i=last,first,-1 do
r[#r+1] = tostring(false)
end
local n = concat(r," ")
if trace_stacker then
s.report("stop: %s",n)
end
return n
end
end
local function change(s,t1,first1,last1,t2,first2,last2)
if s.mode == "switch" then
local n = tostring(t2[last2])
if trace_stacker then
s.report("change: %s",n)
end
return n
else
local r = { }
for i=last1,first1,-1 do
r[#r+1] = tostring(false)
end
local n = concat(r," ")
for i=first2,last2 do
r[#r+1] = tostring(t2[i])
end
if trace_stacker then
s.report("change: %s",n)
end
return n
end
end
function stacker.new(name)
-- to be sped up, mmaybe foo:bar syntax here but then quite some access
local report = logs.reporter("stacker",name or nil)
local s
local stack = { }
local list = { }
local ids = { }
local hash = { }
local hashing = true
local function push(...)
-- todo check if more than 1 argument
for i=1,select("#",...) do
insert(stack,(select(i,...))) -- watch the ()
end
if hashing then
local c = concat(stack,"|")
local n = hash[c]
if not n then
n = #list+1
hash[c] = n
list[n] = fastcopy(stack)
end
insert(ids,n)
return n
else
local n = #list+1
list[n] = fastcopy(stack)
insert(ids,n)
return n
end
end
local function pop()
remove(stack)
remove(ids)
return ids[#ids] or s.unset or -1
end
local function clean()
if #stack == 0 then
if trace_stacker then
s.report("%s list entries, %s stack entries",#list,#stack)
end
end
end
local tops = { }
local top = nil
local switch = nil
local function resolve_reset(mode)
if #tops > 0 then
report("resetting %s left-over states of %a",#tops,name)
end
tops = { }
top = nil
switch = nil
end
local function resolve_begin(mode)
if mode then
switch = mode == "switch"
else
switch = s.mode == "switch"
end
top = { switch = switch }
insert(tops,top)
end
local function resolve_step(ti) -- keep track of changes outside function !
-- todo: optimize for n=1 etc
if not top then
-- report("messed op stacker %a",name)
return
end
local result = nil
local noftop = #top
if ti > 0 then
local current = list[ti]
if current then
local noflist = #current
local nofsame = 0
if noflist > noftop then
for i=1,noflist do
if current[i] == top[i] then
nofsame = i
else
break
end
end
else
for i=1,noflist do
if current[i] == top[i] then
nofsame = i
else
break
end
end
end
local plus = nofsame + 1
if plus <= noftop then
if plus <= noflist then
if switch then
result = s.change(s,top,plus,noftop,current,nofsame,noflist)
else
result = s.change(s,top,plus,noftop,current,plus,noflist)
end
else
if switch then
result = s.change(s,top,plus,noftop,current,nofsame,noflist)
else
result = s.stop(s,top,plus,noftop)
end
end
elseif plus <= noflist then
if switch then
result = s.start(s,current,nofsame,noflist)
else
result = s.start(s,current,plus,noflist)
end
end
top = current
else
if 1 <= noftop then
result = s.stop(s,top,1,noftop)
end
top = { }
end
return result
else
if 1 <= noftop then
result = s.stop(s,top,1,noftop)
end
top = { }
return result
end
end
local function resolve_end()
-- resolve_step(s.unset)
if #tops > 0 then -- was #top brrr
local result = s.stop(s,top,1,#top)
remove(tops)
top = tops[#tops]
switch = top and top.switch
return result
end
end
local function resolve(t)
resolve_begin()
for i=1,#t do
resolve_step(t[i])
end
resolve_end()
end
s = {
name = name or "unknown",
unset = -1,
report = report,
start = start,
stop = stop,
change = change,
push = push,
pop = pop,
clean = clean,
resolve = resolve,
resolve_begin = resolve_begin,
resolve_step = resolve_step,
resolve_end = resolve_end,
resolve_reset = resolve_reset,
}
return s -- we can overload functions
end
-- local s = utilities.stacker.new("demo")
--
-- local unset = s.unset
-- local push = s.push
-- local pop = s.pop
--
-- local t = {
-- unset,
-- unset,
-- push("a"), -- a
-- push("b","c"), -- a b c
-- pop(), -- a b
-- push("d"), -- a b d
-- pop(), -- a b
-- unset,
-- pop(), -- a
-- pop(), -- b
-- unset,
-- unset,
-- }
--
-- s.resolve(t)
-- demostacker = utilities.stacker.new("demos")
--
-- local whatever = {
-- one = "1 0 0 RG 1 0 0 rg",
-- two = "1 1 0 RG 1 1 0 rg",
-- [false] = "0 G 0 g",
-- }
--
-- local concat = table.concat
--
-- local pageliteral = nodes.pool.pageliteral
--
-- function demostacker.start(s,t,first,last)
-- local n = whatever[t[last]]
-- -- s.report("start: %s",n)
-- return pageliteral(n)
-- end
--
-- function demostacker.stop(s,t,first,last)
-- local n = whatever[false]
-- -- s.report("stop: %s",n)
-- return pageliteral(n)
-- end
--
-- function demostacker.change(s,t1,first1,last1,t2,first2,last2)
-- local n = whatever[t2[last2]]
-- -- s.report("change: %s",n)
-- return pageliteral(n)
-- end
--
-- demostacker.mode = "switch"
--
-- local whatever = {
-- one = "/OC /test1 BDC",
-- two = "/OC /test2 BDC",
-- [false] = "EMC",
-- }
--
-- demostacker = utilities.stacker.new("demos")
--
-- function demostacker.start(s,t,first,last)
-- local r = { }
-- for i=first,last do
-- r[#r+1] = whatever[t[i]]
-- end
-- -- s.report("start: %s",concat(r," "))
-- return pageliteral(concat(r," "))
-- end
--
-- function demostacker.stop(s,t,first,last)
-- local r = { }
-- for i=last,first,-1 do
-- r[#r+1] = whatever[false]
-- end
-- -- s.report("stop: %s",concat(r," "))
-- return pageliteral(concat(r," "))
-- end
--
-- function demostacker.change(s,t1,first1,last1,t2,first2,last2)
-- local r = { }
-- for i=last1,first1,-1 do
-- r[#r+1] = whatever[false]
-- end
-- for i=first2,last2 do
-- r[#r+1] = whatever[t2[i]]
-- end
-- -- s.report("change: %s",concat(r," "))
-- return pageliteral(concat(r," "))
-- end
--
-- demostacker.mode = "stack"