summaryrefslogtreecommitdiff
path: root/tex/context/base/node-mig.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/node-mig.lua')
-rw-r--r--tex/context/base/node-mig.lua120
1 files changed, 120 insertions, 0 deletions
diff --git a/tex/context/base/node-mig.lua b/tex/context/base/node-mig.lua
new file mode 100644
index 000000000..f9f0ad231
--- /dev/null
+++ b/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)