diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/node-mig.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/node-mig.lua | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/context/base/node-mig.lua b/Master/texmf-dist/tex/context/base/node-mig.lua new file mode 100644 index 00000000000..f9f0ad23184 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/node-mig.lua @@ -0,0 +1,120 @@ +if not modules then modules = { } end modules ['node-mig'] = { + version = 1.001, + comment = "companion to node-mig.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local format = string.format + +local hlist = node.id('hlist') +local vlist = node.id('vlist') +local insert = node.id('ins') +local mark = node.id('mark') + +local has_attribute = node.has_attribute +local set_attribute = node.set_attribute +local remove_nodes = nodes.remove + +local migrated = attributes.private("migrated") + +local trace_migrations = false + +trackers.register("nodes.migrations", function(v) trace_migrations = v end) + +local migrate_inserts, migrate_marks + +local t_inserts, t_marks, t_sweeps = 0, 0, 0 + +local function locate(head,first,last,ni,nm) + local current = head + while current do + local id = current.id + if id == vlist or id == hlist then + current.list, first, last, ni, nm = locate(current.list,first,last,ni,nm) + current= current.next + elseif migrate_inserts and id == insert then + local insert + head, current, insert = remove_nodes(head,current) + insert.next = nil + if first then + insert.prev, last.next = last, insert + else + insert.prev, first = nil, insert + end + last, ni = insert, ni + 1 + elseif migrate_marks and id == mark then + local mark + head, current, mark = remove_nodes(head,current) + mark.next = nil + if first then + mark.prev, last.next = last, mark + else + mark.prev, first = nil, mark + end + last, nm = mark, nm + 1 + else + current= current.next + end + end + return head, first, last, ni, nm +end + +function nodes.migrate_outwards(head,where) + local done = false + if head then + local current = head + while current do + local id = current.id + if id == vlist or id == hlist and not has_attribute(current,migrated) then + set_attribute(current,migrated,1) + t_sweeps = t_sweeps + 1 + local h = current.list + local first, last, ni, nm + while h do + local id = h.id + if id == vlist or id == hlist then + h, first, last, ni, nm = locate(h,first,last,0,0) + end + h = h.next + end + if first then + t_inserts, t_marks = t_inserts + ni, t_marks + nm + if trace_migrations and (ni > 0 or nm > 0) then + logs.report("nodes","sweep %s, %s inserts and %s marks migrated outwards",t_sweeps,ni,nm) + end + -- inserts after head + local n = current.next + if n then + last.next, n.prev = n, last + end + current.next, first.prev = first, current + done, current = true, last + end + end + current = current.next + end + return head, done + end +end + +experiments.register("marks.migrate", function(v) + if v then + tasks.enableaction("mvlbuilders", "nodes.migrate_outwards") + end + migrate_marks = v +end) + +experiments.register("inserts.migrate", function(v) + if v then + tasks.enableaction("mvlbuilders", "nodes.migrate_outwards") + end + migrate_inserts = v +end) + +statistics.register("node migrations", function() + if trace_migrations and t_sweeps > 0 then + return format("%s sweeps, %s inserts moved, %s marks moved",t_sweeps,t_inserts,t_marks) + end +end) |