summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/mkiv/util-seq.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkiv/util-seq.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-seq.lua370
1 files changed, 154 insertions, 216 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-seq.lua b/Master/texmf-dist/tex/context/base/mkiv/util-seq.lua
index e7a503fafcd..d302ff276f1 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/util-seq.lua
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-seq.lua
@@ -17,39 +17,26 @@ use locals to refer to them when compiling the chain.</p>
-- todo: protect groups (as in tasks)
-local gsub, gmatch = string.gsub, string.gmatch
-local concat, sortedkeys = table.concat, table.sortedkeys
-local type, load, next, tostring = type, load, next, tostring
+local gsub, concat, gmatch = string.gsub, table.concat, string.gmatch
+local type, load = type, load
-utilities = utilities or { }
-local tables = utilities.tables
-local allocate = utilities.storage.allocate
+utilities = utilities or { }
+local tables = utilities.tables
+local allocate = utilities.storage.allocate
-local formatters = string.formatters
-local replacer = utilities.templates.replacer
+local formatters = string.formatters
-local trace_used = false
-local trace_detail = false
-local report = logs.reporter("sequencer")
-local usedcount = 0
-local usednames = { }
+local sequencers = { }
+utilities.sequencers = sequencers
-trackers.register("sequencers.used", function(v) trace_used = true end)
-trackers.register("sequencers.detail",function(v) trace_detail = true end)
-
-local sequencers = { }
-utilities.sequencers = sequencers
-
-local functions = allocate()
-sequencers.functions = functions
+local functions = allocate()
+sequencers.functions = functions
local removevalue = tables.removevalue
local replacevalue = tables.replacevalue
local insertaftervalue = tables.insertaftervalue
local insertbeforevalue = tables.insertbeforevalue
-local usedsequences = { }
-
local function validaction(action)
if type(action) == "string" then
local g = _G
@@ -76,11 +63,9 @@ function sequencers.new(t) -- was reset
gskip = { },
dirty = true,
runner = nil,
- steps = 0,
}
if t then
s.arguments = t.arguments
- s.templates = t.templates
s.returnvalues = t.returnvalues
s.results = t.results
local name = t.name
@@ -101,142 +86,120 @@ function sequencers.new(t) -- was reset
end
function sequencers.prependgroup(t,group,where)
- if t and group then
- t = known[t]
- if t then
- local order = t.order
- removevalue(order,group)
- insertbeforevalue(order,where,group)
- t.list[group] = { }
- t.dirty = true
- t.runner = nil
- end
+ t = known[t]
+ if t then
+ local order = t.order
+ removevalue(order,group)
+ insertbeforevalue(order,where,group)
+ t.list[group] = { }
+ t.dirty = true
+ t.runner = nil
end
end
function sequencers.appendgroup(t,group,where)
- if t and group then
- t = known[t]
- if t then
- local order = t.order
- removevalue(order,group)
- insertaftervalue(order,where,group)
- t.list[group] = { }
- t.dirty = true
- t.runner = nil
- end
+ t = known[t]
+ if t then
+ local order = t.order
+ removevalue(order,group)
+ insertaftervalue(order,where,group)
+ t.list[group] = { }
+ t.dirty = true
+ t.runner = nil
end
end
function sequencers.prependaction(t,group,action,where,kind,force)
- if t and group and action then
- t = known[t]
- if t then
- local g = t.list[group]
- if g and (force or validaction(action)) then
- removevalue(g,action)
- insertbeforevalue(g,where,action)
- t.kind[action] = kind
- t.dirty = true
- t.runner = nil
- end
+ t = known[t]
+ if t then
+ local g = t.list[group]
+ if g and (force or validaction(action)) then
+ removevalue(g,action)
+ insertbeforevalue(g,where,action)
+ t.kind[action] = kind
+ t.dirty = true
+ t.runner = nil
end
end
end
function sequencers.appendaction(t,group,action,where,kind,force)
- if t and group and action then
- t = known[t]
- if t then
- local g = t.list[group]
- if g and (force or validaction(action)) then
- removevalue(g,action)
- insertaftervalue(g,where,action)
- t.kind[action] = kind
- t.dirty = true
- t.runner = nil
- end
+ t = known[t]
+ if t then
+ local g = t.list[group]
+ if g and (force or validaction(action)) then
+ removevalue(g,action)
+ insertaftervalue(g,where,action)
+ t.kind[action] = kind
+ t.dirty = true
+ t.runner = nil
end
end
end
function sequencers.enableaction(t,action)
- if t and action then
- t = known[t]
- if t then
- t.askip[action] = false
- t.dirty = true
- t.runner = nil
- end
+ t = known[t]
+ if t then
+ t.askip[action] = false
+ t.dirty = true
+ t.runner = nil
end
end
function sequencers.disableaction(t,action)
- if t and action then
- t = known[t]
- if t then
- t.askip[action] = true
- t.dirty = true
- t.runner = nil
- end
+ t = known[t]
+ if t then
+ t.askip[action] = true
+ t.dirty = true
+ t.runner = nil
end
end
function sequencers.enablegroup(t,group)
- if t and group then
- t = known[t]
- if t then
- t.gskip[group] = false
- t.dirty = true
- t.runner = nil
- end
+ t = known[t]
+ if t then
+ t.gskip[action] = false
+ t.dirty = true
+ t.runner = nil
end
end
function sequencers.disablegroup(t,group)
- if t and group then
- t = known[t]
- if t then
- t.gskip[group] = true
- t.dirty = true
- t.runner = nil
- end
+ t = known[t]
+ if t then
+ t.gskip[action] = true
+ t.dirty = true
+ t.runner = nil
end
end
function sequencers.setkind(t,action,kind)
- if t and action then
- t = known[t]
- if t then
- t.kind[action] = kind
- t.dirty = true
- t.runner = nil
- end
+ t = known[t]
+ if t then
+ t.kind[action] = kind
+ t.dirty = true
+ t.runner = nil
end
end
function sequencers.removeaction(t,group,action,force)
- if t and group and action then
- t = known[t]
- local g = t and t.list[group]
- if g and (force or validaction(action)) then
- removevalue(g,action)
- t.dirty = true
- t.runner = nil
- end
+ t = known[t]
+ local g = t and t.list[group]
+ if g and (force or validaction(action)) then
+ removevalue(g,action)
+ t.dirty = true
+ t.runner = nil
end
end
function sequencers.replaceaction(t,group,oldaction,newaction,force)
- if t and group and oldaction and newaction then
- t = known[t]
- if t then
- local g = t.list[group]
- if g and (force or validaction(oldaction)) then
- replacevalue(g,oldaction,newaction)
- t.dirty = true
- t.runner = nil
- end
+ t = known[t]
+ if t then
+ local g = t.list[group]
+ if g and (force or validaction(oldaction)) then
+ replacevalue(g,oldaction,newaction)
+ t.dirty = true
+ t.runner = nil
end
end
end
@@ -246,19 +209,9 @@ local function localize(str)
end
local function construct(t)
- local list = t.list
- local order = t.order
- local kind = t.kind
- local gskip = t.gskip
- local askip = t.askip
- local name = t.name or "?"
- local arguments = t.arguments or "..."
- local returnvalues = t.returnvalues
- local results = t.results
- local variables = { }
- local calls = { }
- local n = 0
- usedcount = usedcount + 1
+ local list, order, kind, gskip, askip = t.list, t.order, t.kind, t.gskip, t.askip
+ local arguments, returnvalues, results = t.arguments or "...", t.returnvalues, t.results
+ local variables, calls, n = { }, { }, 0
for i=1,#order do
local group = order[i]
if not gskip[group] then
@@ -266,11 +219,6 @@ local function construct(t)
for i=1,#actions do
local action = actions[i]
if not askip[action] then
- if trace_used then
- local action = tostring(action)
- report("%02i: category %a, group %a, action %a",usedcount,name,group,action)
- usednames[action] = true
- end
local localized
if type(action) == "function" then
local name = localize(tostring(action))
@@ -294,7 +242,6 @@ local function construct(t)
end
end
t.dirty = false
- t.steps = n
if n == 0 then
t.compiled = ""
else
@@ -306,27 +253,30 @@ local function construct(t)
t.compiled = formatters["%s\nreturn function(%s)\n%s\nend"](variables,arguments,calls)
end
end
+-- print(t.compiled)
return t.compiled -- also stored so that we can trace
end
sequencers.tostring = construct
sequencers.localize = localize
-compile = function(t,compiler,...) -- already referred to in sequencers.new
+compile = function(t,compiler,n) -- already referred to in sequencers.new
local compiled
if not t or type(t) == "string" then
+ -- weird ... t.compiled = t .. so
return false
end
if compiler then
- compiled = compiler(t,...)
+ compiled = compiler(t,n)
t.compiled = compiled
else
- compiled = construct(t,...)
+ compiled = construct(t,n)
end
local runner
if compiled == "" then
runner = false
else
+-- inspect(compiled)
runner = compiled and load(compiled)() -- we can use loadstripped here
end
t.runner = runner
@@ -335,45 +285,52 @@ end
sequencers.compile = compile
-function sequencers.nodeprocessor(t,nofarguments)
- --
- local templates = nofarguments
- --
- if type(templates) ~= "table" then
- return ""
- end
- --
- local replacers = { }
- for k, v in next, templates do
- replacers[k] = replacer(v)
- end
- --
- local construct = replacers.process
- local step = replacers.step
- if not construct or not step then
- return ""
- end
- --
- local calls = { }
- local aliases = { }
- local ncalls = 0
- local naliases = 0
- local f_alias = formatters["local %s = %s"]
- --
- local list = t.list
- local order = t.order
- local kind = t.kind
- local gskip = t.gskip
- local askip = t.askip
- local name = t.name or "?"
- local steps = 0
- usedcount = usedcount + 1
- --
- if trace_detail then
- naliases = naliases + 1
- aliases[naliases] = formatters["local report = logs.reporter('sequencer',%q)"](name)
- ncalls = ncalls + 1
- calls[ncalls] = [[report("start")]]
+-- we used to deal with tail as well but now that the lists are always
+-- double linked and the kernel function no longer expect tail as
+-- argument we stick to head and done (done can probably also go
+-- as luatex deals with return values efficiently now .. in the
+-- past there was some copying involved, but no longer)
+
+-- todo: use sequencer (can have arguments and returnvalues etc now)
+
+local template_yes_state = [[
+%s
+return function(head%s)
+ local ok, done = false, false
+%s
+ return head, done
+end]]
+
+local template_yes_nostate = [[
+%s
+return function(head%s)
+%s
+ return head, true
+end]]
+
+local template_nop = [[
+return function()
+ return false, false
+end]]
+
+function sequencers.nodeprocessor(t,nofarguments) -- todo: handle 'kind' in plug into tostring
+ local list, order, kind, gskip, askip = t.list, t.order, t.kind, t.gskip, t.askip
+ local nostate = t.nostate
+ local vars, calls, args, n = { }, { }, nil, 0
+ if nofarguments == 0 then
+ args = ""
+ elseif nofarguments == 1 then
+ args = ",one"
+ elseif nofarguments == 2 then
+ args = ",one,two"
+ elseif nofarguments == 3 then -- from here on probably slower than ...
+ args = ",one,two,three"
+ elseif nofarguments == 4 then
+ args = ",one,two,three,four"
+ elseif nofarguments == 5 then
+ args = ",one,two,three,four,five"
+ else
+ args = ",..."
end
for i=1,#order do
local group = order[i]
@@ -382,47 +339,28 @@ function sequencers.nodeprocessor(t,nofarguments)
for i=1,#actions do
local action = actions[i]
if not askip[action] then
- steps = steps + 1
- if trace_used or trace_detail then
- local action = tostring(action)
- report("%02i: category %a, group %a, action %a",usedcount,name,group,action)
- usednames[action] = true
- end
- if trace_detail then
- ncalls = ncalls + 1
- calls[ncalls] = formatters[ [[report(" step %a, action %a")]] ](steps,tostring(action))
- end
local localized = localize(action)
- local onestep = replacers[kind[action]] or step
- naliases = naliases + 1
- ncalls = ncalls + 1
- aliases[naliases] = f_alias(localized,action)
- calls [ncalls] = onestep { action = localized }
+ n = n + 1
+ vars[n] = formatters["local %s = %s"](localized,action)
+ -- only difference with tostring is kind and rets (why no return)
+ if nostate then
+ if kind[action] == "nohead" then
+ calls[n] = formatters[" %s(head%s)"](localized,args)
+ else
+ calls[n] = formatters[" head = %s(head%s)"](localized,args)
+ end
+ else
+ if kind[action] == "nohead" then
+ calls[n] = formatters[" ok = %s(head%s) if ok then done = true end"](localized,args)
+ else
+ calls[n] = formatters[" head, ok = %s(head%s) if ok then done = true end"](localized,args)
+ end
+ end
end
end
end
end
- t.steps = steps
- local processor
- if steps == 0 then
- processor = templates.default or construct { }
- else
- if trace_detail then
- ncalls = ncalls + 1
- calls[ncalls] = [[report("stop")]]
- end
- processor = construct {
- localize = concat(aliases,"\n"),
- actions = concat(calls,"\n"),
- }
- end
- -- processor = "print('running : " .. (t.name or "?") .. "')\n" .. processor
+ local processor = #calls > 0 and formatters[nostate and template_yes_nostate or template_yes_state](concat(vars,"\n"),args,concat(calls,"\n")) or template_nop
-- print(processor)
return processor
end
-
-statistics.register("used sequences",function()
- if next(usednames) then
- return concat(sortedkeys(usednames)," ")
- end
-end)