summaryrefslogtreecommitdiff
path: root/tex/context/base/util-sta.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/util-sta.lua')
-rw-r--r--tex/context/base/util-sta.lua684
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"