diff options
Diffstat (limited to 'tex/context/base/util-sta.lua')
-rw-r--r-- | tex/context/base/util-sta.lua | 684 |
1 files changed, 342 insertions, 342 deletions
diff --git a/tex/context/base/util-sta.lua b/tex/context/base/util-sta.lua index 1a61ec4e6..1ea713a76 100644 --- a/tex/context/base/util-sta.lua +++ b/tex/context/base/util-sta.lua @@ -1,342 +1,342 @@ -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) - - local s - - local stack = { } - local list = { } - local ids = { } - local hash = { } - - local hashing = true - - local function push(...) - 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, switch - - 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 - 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) - local noftop = #top - if noftop > 0 then - 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 - - local report = logs.reporter("stacker",name or nil) - - 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, - } - - 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 pdfliteral = nodes.pool.pdfliteral --- --- function demostacker.start(s,t,first,last) --- local n = whatever[t[last]] --- -- s.report("start: %s",n) --- return pdfliteral(n) --- end --- --- function demostacker.stop(s,t,first,last) --- local n = whatever[false] --- -- s.report("stop: %s",n) --- return pdfliteral(n) --- end --- --- function demostacker.change(s,t1,first1,last1,t2,first2,last2) --- local n = whatever[t2[last2]] --- -- s.report("change: %s",n) --- return pdfliteral(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 pdfliteral(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 pdfliteral(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 pdfliteral(concat(r," ")) --- end --- --- demostacker.mode = "stack" +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)
+
+ local s
+
+ local stack = { }
+ local list = { }
+ local ids = { }
+ local hash = { }
+
+ local hashing = true
+
+ local function push(...)
+ 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, switch
+
+ 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
+ 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)
+ local noftop = #top
+ if noftop > 0 then
+ 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
+
+ local report = logs.reporter("stacker",name or nil)
+
+ 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,
+ }
+
+ 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 pdfliteral = nodes.pool.pdfliteral
+--
+-- function demostacker.start(s,t,first,last)
+-- local n = whatever[t[last]]
+-- -- s.report("start: %s",n)
+-- return pdfliteral(n)
+-- end
+--
+-- function demostacker.stop(s,t,first,last)
+-- local n = whatever[false]
+-- -- s.report("stop: %s",n)
+-- return pdfliteral(n)
+-- end
+--
+-- function demostacker.change(s,t1,first1,last1,t2,first2,last2)
+-- local n = whatever[t2[last2]]
+-- -- s.report("change: %s",n)
+-- return pdfliteral(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 pdfliteral(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 pdfliteral(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 pdfliteral(concat(r," "))
+-- end
+--
+-- demostacker.mode = "stack"
|