diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkiv/node-ppt.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/mkiv/node-ppt.lua | 173 |
1 files changed, 122 insertions, 51 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-ppt.lua b/Master/texmf-dist/tex/context/base/mkiv/node-ppt.lua index 485e742b64a..5ebfca87d14 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-ppt.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-ppt.lua @@ -26,14 +26,12 @@ local getid = nuts.getid local getnext = nuts.getnext local getprev = nuts.getprev local getsubtype = nuts.getsubtype +local getfield = nuts.getfield local getlist = nuts.getlist local setlist = nuts.setlist -local getprop = nuts.getprop - local removenode = nuts.remove - -local nextnode = nuts.traversers.node -local nextwhatsit = nuts.traversers.whatsit +local traverse = nuts.traverse +local traverse_id = nuts.traverse_id local nodecodes = nodes.nodecodes local whatsitcodes = nodes.whatsitcodes @@ -41,17 +39,18 @@ local whatsitcodes = nodes.whatsitcodes local whatsit_code = nodecodes.whatsit local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist - -local userdefinedwhatsit_code = whatsitcodes.userdefined +local userdefined_code = whatsitcodes.userdefined local nodepool = nodes.pool -local new_usernode = nodepool.usernode +local new_usernumber = nodepool.usernumber local variables = interfaces.variables local v_before = variables.before local v_after = variables.after local v_here = variables.here +local cache = { } +local nofslots = 0 local property_id = nodepool.userids["property"] local properties = nodes.properties @@ -72,8 +71,15 @@ local function register(where,data,...) where = v_after end if data then + local data = { where, data, ... } nofslots = nofslots + 1 - return new_usernode(property_id,{ where, data, ... }) + if nofslots > 1 then + cache[nofslots] = data + else + -- report("restarting attacher") + cache = { data } -- also forces collection + end + return new_usernumber(property_id,nofslots) end end @@ -102,9 +108,17 @@ local f_delayed = formatters["return function(target,head,where,propdata,paren local f_immediate = formatters["return function(target,head,where,propdata) %s end"] local nofdelayed = 0 -- better is to keep track of it per page ... we can have deleted nodes with properties -local nofslots = 0 function actions.delayed(target,head,where,propdata,code,...) -- this one is used at the tex end +-- local kind = type(code) +-- if kind == "string" then +-- code, err = load(f_delayed(code)) +-- if code then +-- code = code() +-- end +-- elseif kind ~= "function" then +-- code = nil +-- end if code then local delayed = propdata.delayed if delayed then @@ -117,6 +131,15 @@ function actions.delayed(target,head,where,propdata,code,...) -- this one is use end function actions.fdelayed(target,head,where,propdata,code,...) -- this one is used at the tex end +-- local kind = type(code) +-- if kind == "string" then +-- code, err = load(f_delayed(code)) +-- if code then +-- code = code() +-- end +-- elseif kind ~= "function" then +-- code = nil +-- end if code then local delayed = propdata.delayed if delayed then @@ -147,41 +170,81 @@ function actions.immediate(target,head,where,propdata,code,...) -- this one is u end end +-- another experiment (a table or function closure are equally efficient); a function +-- is easier when we want to experiment with different (compatible) implementations + +-- local nutpool = nuts.pool +-- local nut_usernumber = nutpool.usernumber + +-- function nodes.nuts.pool.deferredfunction(...) +-- nofdelayed = nofdelayed + 1 +-- local n = nut_usernumber(property_id,0) +-- propertydata[n] = { deferred = { ... } } +-- return n +-- end + +-- function nodes.nuts.pool.deferredfunction(f) +-- nofdelayed = nofdelayed + 1 +-- local n = nut_usernumber(property_id,0) +-- propertydata[n] = { deferred = f } +-- return n +-- end + +-- maybe actions will get parent too + local function delayed(head,parent) -- direct based - for target, id in nextnode, head do + for target in traverse(head) do local p = propertydata[target] if p then - local delayed = p.delayed - if delayed then - for i=1,#delayed do - local d = delayed[i] - local code = d[2] - local kind = type(code) - if kind == "string" then - code, err = load(f_delayed(code)) - if code then - code = code() + -- local deferred = p.deferred -- kind of late lua (but too soon as we have no access to pdf.h/v) + -- if deferred then + -- -- if #deferred > 0 then + -- -- deferred[1](unpack(deferred,2)) + -- -- else + -- -- deferred[1]() + -- -- end + -- deferred() + -- p.deferred = false + -- if nofdelayed == 1 then + -- nofdelayed = 0 + -- return head + -- else + -- nofdelayed = nofdelayed - 1 + -- end + -- else + local delayed = p.delayed + if delayed then + for i=1,#delayed do + local d = delayed[i] + local code = d[2] + local kind = type(code) + if kind == "string" then + code, err = load(f_delayed(code)) + if code then + code = code() + end end - end - local where = d[1] - if where then - local h = code(target,where,head,p,parent,unpack(d,3)) -- target where propdata head parent - if h and h ~= head then - head = h + local where = d[1] + if where then + local h = code(target,where,head,p,parent,unpack(d,3)) -- target where propdata head parent + if h and h ~= head then + head = h + end + else + code(unpack(d,3)) end + end + p.delayed = nil + if nofdelayed == 1 then + nofdelayed = 0 + return head else - code(unpack(d,3)) + nofdelayed = nofdelayed - 1 end end - p.delayed = nil - if nofdelayed == 1 then - nofdelayed = 0 - return head - else - nofdelayed = nofdelayed - 1 - end - end + -- end end + local id = getid(target) if id == hlist_code or id == vlist_code then local list = getlist(target) if list then @@ -205,13 +268,14 @@ function properties.delayed(head) -- if nofdelayed > 0 then -- if next(propertydata) then starttiming(properties) - head = delayed(head) + head = delayed(tonut(head)) stoptiming(properties) + return tonode(head), true -- done in shipout anyway -- else -- delayed = 0 - -- end + -- end end - return head + return head, false end -- more explicit ones too @@ -220,7 +284,7 @@ local anchored = { [v_before] = function(n) while n do n = getprev(n) - if getid(n) == whatsit_code and getsubtype(n) == user_code and getprop(n,"id") == property_id then + if getid(n) == whatsit_code and getsubtype(n) == user_code and getfield(n,"user_id") == property_id then -- continue else return n @@ -232,7 +296,7 @@ local anchored = { n = getnext(n) if getid(n) == whatsit_code then local subtype = getsubtype(n) - if (subtype == userdefinedwhatsit_code and getprop(n,"id") == property_id) then + if (subtype == userdefined_code and getfield(n,"user_id") == property_id) then -- continue else return n @@ -256,22 +320,26 @@ end) function properties.attach(head) if nofslots <= 0 then - return head + return head, false end + local done = false local last = nil + local head = tonut(head) starttiming(properties) - for source, subtype in nextwhatsit, head do - if subtype == userdefinedwhatsit_code then + for source in traverse_id(whatsit_code,head) do + if getsubtype(source) == userdefined_code then if last then removenode(head,last,true) last = nil end - if getprop(source,"id") == property_id then - local data = getprop(source,"data") + if getfield(source,"user_id") == property_id then + local slot = getfield(source,"value") + local data = cache[slot] if data then + cache[slot] = nil local where = data[1] local target = anchored[where](source) if target then @@ -325,7 +393,7 @@ function properties.attach(head) target,nodecodes[getid(target)],serialize(propertydata[target],false)) end end - if nofslots == 1 then + if nofslots == 1 then nofslots = 0 last = source break @@ -344,22 +412,25 @@ function properties.attach(head) stoptiming(properties) - return head + return head, done end +local tasks = nodes.tasks + -- maybe better hard coded in-place +-- tasks.prependaction("processors","before","nodes.properties.attach") +-- tasks.appendaction("shipouts","normalizers","nodes.properties.delayed") + statistics.register("properties processing time", function() return statistics.elapsedseconds(properties) end) -- only for development --- local tasks = nodes.tasks --- -- local function show(head,level,report) --- for target in nextnode, head do +-- for target in traverse(head) do -- local p = propertydata[target] -- if p then -- report("level %i, node %i, id %s, data %s", |