diff options
Diffstat (limited to 'tex/context/base/mkxl/node-tsk.lmt')
-rw-r--r-- | tex/context/base/mkxl/node-tsk.lmt | 796 |
1 files changed, 796 insertions, 0 deletions
diff --git a/tex/context/base/mkxl/node-tsk.lmt b/tex/context/base/mkxl/node-tsk.lmt new file mode 100644 index 000000000..ca7c7fee4 --- /dev/null +++ b/tex/context/base/mkxl/node-tsk.lmt @@ -0,0 +1,796 @@ +if not modules then modules = { } end modules ['node-tsk'] = { + version = 1.001, + comment = "companion to node-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This might move to task-* and become less code as in sequencers +-- we already have dirty flags as well. On the other hand, nodes are +-- rather specialized and here we focus on node related tasks. + +local format = string.format + +local trace_tasks = false trackers.register("tasks.creation", function(v) trace_tasks = v end) + +local report_tasks = logs.reporter("tasks") + +local allocate = utilities.storage.allocate + +local context = context +local nodes = nodes + +local tasks = nodes.tasks or { } +nodes.tasks = tasks + +local tasksdata = { } -- no longer public + +local sequencers = utilities.sequencers +local compile = sequencers.compile +local nodeprocessor = sequencers.nodeprocessor + +local newsequencer = sequencers.new + +local appendgroup = sequencers.appendgroup +----- prependgroup = sequencers.prependgroup +----- replacegroup = sequencers.replacegroup +local enablegroup = sequencers.enablegroup +local disablegroup = sequencers.disablegroup + +local appendaction = sequencers.appendaction +local prependaction = sequencers.prependaction +local replaceaction = sequencers.replaceaction +local enableaction = sequencers.enableaction +local disableaction = sequencers.disableaction + +local frozengroups = "no" + +function tasks.freeze(kind) + frozengroups = kind or "tolerant" -- todo: hook into jobname +end + +function tasks.new(specification) -- was: name,arguments,list + local name = specification.name + local sequence = specification.sequence + if name and sequence then + local tasklist = newsequencer { + name = name + -- we can move more to the sequencer now .. todo + } + tasksdata[name] = { + name = name, + list = tasklist, + runner = false, + frozen = { }, + processor = specification.processor or nodeprocessor, + -- could be metatable but best freeze it + arguments = specification.arguments or 0, + templates = specification.templates, + } + for l=1,#sequence do + appendgroup(tasklist,sequence[l]) + end + end +end + +local function valid(name) + local data = tasksdata[name] + if not data then + report_tasks("unknown task %a",name) + else + return data + end +end + +local function validgroup(name,group,what) + local data = tasksdata[name] + if not data then + report_tasks("unknown task %a",name) + else + local frozen = data.frozen[group] + if frozen then + if frozengroup == "no" then + -- default + elseif frozengroup == "strict" then + report_tasks("warning: group %a of task %a is frozen, %a applied but not supported",group,name,what) + return + else -- if frozengroup == "tolerant" then + report_tasks("warning: group %a of task %a is frozen, %a ignored",group,name,what) + end + end + return data + end +end + +function tasks.freezegroup(name,group) + local data = valid(name) + if data then + data.frozen[group] = true + end +end + +function tasks.restart(name) + local data = valid(name) + if data then + data.runner = false + end +end + +function tasks.enableaction(name,action) + local data = valid(name) + if data then + enableaction(data.list,action) + data.runner = false + end +end + +function tasks.disableaction(name,action) + local data = valid(name) + if data then + disableaction(data.list,action) + data.runner = false + end +end + +function tasks.replaceaction(name,group,oldaction,newaction) + local data = valid(name) + if data then + replaceaction(data.list,group,oldaction,newaction) + data.runner = false + end +end + +do + + local enableaction = tasks.enableaction + local disableaction = tasks.disableaction + + function tasks.setaction(name,action,value) + if value then + enableaction(name,action) + else + disableaction(name,action) + end + end + +end + +function tasks.enablegroup(name,group) + local data = validgroup(name,"enable group") + if data then + enablegroup(data.list,group) + data.runner = false + end +end + +function tasks.disablegroup(name,group) + local data = validgroup(name,"disable group") + if data then + disablegroup(data.list,group) + data.runner = false + end +end + +function tasks.appendaction(name,group,action,where,kind,state) + local data = validgroup(name,"append action") + if data then + local list = data.list + appendaction(list,group,action,where,kind) + if state == "disabled" or (state == "production" and environment.initex) then + disableaction(list,action) + end + data.runner = false + end +end + +function tasks.prependaction(name,group,action,where,kind,state) + local data = validgroup(name,"prepend action") + if data then + local list = data.list + prependaction(list,group,action,where,kind) + if state == "disabled" or (state == "production" and environment.initex) then + disableaction(list,action) + end + data.runner = false + end +end + +function tasks.removeaction(name,group,action) + local data = validgroup(name,"remove action") + if data then + removeaction(data.list,group,action) + data.runner = false + end +end + +function tasks.showactions(name,group,action,where,kind) + local data = valid(name) + if data then + report_tasks("task %a, list:\n%s",name,nodeprocessor(data.list)) + end +end + +-- Optimizing for the number of arguments makes sense, but getting rid of +-- the nested call (no problem but then we also need to register the +-- callback with this mechanism so that it gets updated) does not save +-- much time (24K calls on mk.tex). + +local created, total = 0, 0 + +statistics.register("node list callback tasks", function() + if total > 0 then + return format("%s unique task lists, %s instances (re)created, %s calls",table.count(tasksdata),created,total) + else + return nil + end +end) + +local function create(data,t) + created = created + 1 + local runner = compile(data.list,data.processor,t) + if trace_tasks then + report_tasks("creating runner %a, %i actions enabled",t.name,data.list.steps or 0) + end + data.runner = runner + return runner +end + +function tasks.actions(name) + local data = tasksdata[name] + if data then + local t = data.templates + if t then + t.name = data.name + return function(...) + total = total + 1 + return (data.runner or create(data,t))(...) + end + end + end + return nil +end + +function tasks.table(name) --maybe move this to task-deb.lua + local tsk = tasksdata[name] + local lst = tsk and tsk.list + local HL, NC, NR, bold, type = context.HL, context.NC, context.NR, context.bold, context.type + if lst then + local list, order = lst.list, lst.order + if list and order then + context.starttabulate { "|l|l|" } + NC() bold("category") NC() bold("function") NC() NR() + for i=1,#order do + HL() + local o = order[i] + local l = list[o] + if #l == 0 then + NC() type(o) NC() context("unset") NC() NR() + else + local done = false + for k, v in table.sortedhash(l) do + NC() if not done then type(o) done = true end NC() type(v) NC() NR() + end + end + end + context.stoptabulate() + end + end +end + +-- -- shipouts everypar -- -- + +-- the shipout handlers acts on boxes so we don't need to return something +-- and also don't need to keep the state (done) + +local templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +return function(head) + local nuthead = tonut(head) + +%actions% + return tonode(nuthead) +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead)))) +]], + +nut = [[ + nuthead = %action%(nuthead) +]], + +nohead = [[ + %action%(tonode(nuthead)) +]], + +nonut = [[ + %action%(nuthead) +]], + +} + +tasks.new { + name = "shipouts", + processor = nodeprocessor, + sequence = { + "before", -- users + "normalizers", -- system + "finishers", -- system + "after", -- users + "wrapup", -- system + }, + templates = templates +} + +tasks.new { + name = "everypar", + processor = nodeprocessor, + sequence = { + "before", -- users + "normalizers", -- system + "after", -- users + }, + templates = templates, +} + +-- -- finalizers -- -- + +tasks.new { + name = "finalizers", + sequence = { + "before", -- for users + "normalizers", + "fonts", + "lists", + "after", -- for users + }, + processor = nodeprocessor, + templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +return function(head,groupcode) + local nuthead = tonut(head) + +%actions% + return tonode(nuthead) +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead),groupcode))) +]], + +nut = [[ + nuthead = %action%(nuthead,groupcode) +]], + +nohead = [[ + %action%(tonode(nuthead),groupcode) +]], + +nonut = [[ + %action%(nuthead,groupcode) +]], + + } +} + +-- -- processors -- -- + +tasks.new { + name = "processors", + processor = nodeprocessor, + sequence = { + "before", -- for users + "normalizers", + "characters", + "words", + "fonts", + "lists", + "after", -- for users + }, + templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +return function(head,groupcode,size,packtype,direction,attributes) + local nuthead = tonut(head) + +%actions% + return tonode(nuthead) +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead),groupcode,size,packtype,direction,attributes))) +]], + +nut = [[ + nuthead = %action%(nuthead,groupcode,size,packtype,direction,attributes) +]], + +nohead = [[ + %action%(tonode(nuthead),groupcode,size,packtype,direction,attributes) +]], + +nonut = [[ + %action%(nuthead,groupcode,size,packtype,direction,attributes) +]], + + } +} + +tasks.new { + name = "finalizers", + processor = nodeprocessor, + sequence = { + "before", -- for users + "normalizers", + "fonts", + "lists", + "after", -- for users + }, + templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +return function(head) + local nuthead = tonut(head) + +%actions% + return tonode(nuthead) +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead)))) +]], + +nut = [[ + nuthead = %action%(nuthead) +]], + +nohead = [[ + %action%(tonode(nuthead)) +]], + +nonut = [[ + %action%(nuthead) +]], + + } +} + +tasks.new { + name = "mvlbuilders", + processor = nodeprocessor, + sequence = { + "before", -- for users + "normalizers", + "after", -- for users + }, + templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +return function(head,groupcode) + local nuthead = tonut(head) + +%actions% + return tonode(nuthead) +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead),groupcode))) +]], + +nut = [[ + nuthead = %action%(nuthead,groupcode) +]], + +nohead = [[ + %action%(tonode(nuthead),groupcode) +]], + +nonut = [[ + %action%(nuthead,groupcode) +]], + + } +} + +tasks.new { + name = "vboxbuilders", + processor = nodeprocessor, + sequence = { + "before", -- for users + "normalizers", + "after", -- for users + }, + templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +return function(head,groupcode,size,packtype,maxdepth,direction) + local nuthead = tonut(head) + +%actions% + return tonode(nuthead) +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead),groupcode,size,packtype,maxdepth,direction))) +]], + +nut = [[ + nuthead = %action%(nuthead,groupcode,size,packtype,maxdepth,direction) +]], + +nohead = [[ + %action%(tonode(nuthead),groupcode,size,packtype,maxdepth,direction) +]], + +nonut = [[ + %action%(nuthead,groupcode,size,packtype,maxdepth,direction) +]], + + } + +} + +tasks.new { + name = "contributers", + processor = nodeprocessor, + sequence = { + "before", -- for users + "normalizers", + "after", -- for users + }, + templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +-- we operate exclusively on nuts + +return function(nuthead,groupcode,nutline) +%actions% + return nuthead +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead),groupcode,line))) +]], + +nut = [[ + nuthead = %action%(nuthead,groupcode,nutline) +]], + +nohead = [[ + %action%(tonode(nuthead),groupcode,line) +]], + +nonut = [[ + %action%(nuthead,groupcode,nutline) +]], + + } +} + +-- -- math -- -- + +tasks.new { + name = "math", + processor = nodeprocessor, + sequence = { + "before", + "normalizers", + "builders", + "after", + }, + templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +return function(head,style,penalties) + local nuthead = tonut(head) + +%actions% + return tonode(nuthead) +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead),style,penalties))) +]], + +nut = [[ + nuthead = %action%(nuthead,style,penalties) +]], + +nohead = [[ + %action%(tonode(nuthead),style,penalties) +]], + +nonut = [[ + %action%(nuthead,style,penalties) +]], + + } +} + +-- tasks.new { +-- name = "parbuilders", +-- arguments = 1, +-- processor = nodeprocessor, +-- sequence = { +-- "before", -- for users +-- "lists", +-- "after", -- for users +-- } +-- } + +-- tasks.new { +-- name = "pagebuilders", +-- arguments = 5, +-- processor = nodeprocessor, +-- sequence = { +-- "before", -- for users +-- "lists", +-- "after", -- for users +-- } +-- } + +-- for now quite useless (too fuzzy) +-- +-- tasks.new { +-- name = "listbuilders", +-- processor = nodeprocessor, +-- sequence = { +-- "before", -- for users +-- "normalizers", +-- "after", -- for users +-- }, +-- templates = { +-- -- we don't need a default +-- default = [[ +-- return function(box,location,prevdepth) +-- return box, prevdepth +-- end +-- ]], +-- process = [[ +-- %localize% +-- return function(box,location,prevdepth,mirrored) +-- %actions% +-- return box, prevdepth +-- end +-- ]], +-- step = [[ +-- box, prevdepth = %action%(box,location,prevdepth,mirrored) +-- ]], +-- }, +-- } + +-- -- math -- -- + +-- not really a node processor + +-- tasks.new { +-- name = "newpar", +-- processor = nodeprocessor, +-- sequence = { +-- "before", +-- "normalizers", +-- "after", +-- }, +-- templates = { +-- +-- default = [[ +-- return function(mode,indent) +-- return indent +-- end +-- ]], +-- +-- process = [[ +-- %localize% +-- +-- return function(mode,indent) +-- +-- %actions% +-- return indent +-- end +-- ]], +-- +-- step = [[ +-- indent = %action%(mode,indent) +-- ]], +-- +-- } +-- } |