summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/node-mig.lua
diff options
context:
space:
mode:
authorContext Git Mirror Bot <phg42.2a@gmail.com>2016-01-12 17:15:07 +0100
committerContext Git Mirror Bot <phg42.2a@gmail.com>2016-01-12 17:15:07 +0100
commit8d8d528d2ad52599f11250cfc567fea4f37f2a8b (patch)
tree94286bc131ef7d994f9432febaf03fe23d10eef8 /tex/context/base/mkiv/node-mig.lua
parentf5aed2e51223c36c84c5f25a6cad238b2af59087 (diff)
downloadcontext-8d8d528d2ad52599f11250cfc567fea4f37f2a8b.tar.gz
2016-01-12 16:26:00
Diffstat (limited to 'tex/context/base/mkiv/node-mig.lua')
-rw-r--r--tex/context/base/mkiv/node-mig.lua165
1 files changed, 165 insertions, 0 deletions
diff --git a/tex/context/base/mkiv/node-mig.lua b/tex/context/base/mkiv/node-mig.lua
new file mode 100644
index 000000000..24bebb0cc
--- /dev/null
+++ b/tex/context/base/mkiv/node-mig.lua
@@ -0,0 +1,165 @@
+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"
+}
+
+-- todo: insert_after
+
+local format = string.format
+
+local trace_migrations = false trackers.register("nodes.migrations", function(v) trace_migrations = v end)
+
+local report_nodes = logs.reporter("nodes","migrations")
+
+local attributes = attributes
+local nodes = nodes
+local tasks = nodes.tasks
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+
+local getnext = nuts.getnext
+local getid = nuts.getid
+local getlist = nuts.getlist
+local getattr = nuts.getattr
+
+local setfield = nuts.setfield
+local setattr = nuts.setattr
+local setlink = nuts.setlink
+local setlist = nuts.setlist
+local setprev = nuts.setprev
+local setnext = nuts.setnext
+
+local remove_node = nuts.remove
+
+local nodecodes = nodes.nodecodes
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local insert_code = nodecodes.ins
+local mark_code = nodecodes.mark
+
+local a_migrated = attributes.private("migrated")
+
+local migrate_inserts, migrate_marks, inserts_too
+
+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 = getid(current)
+ if id == vlist_code or id == hlist_code then
+ local list = getlist(current)
+ if list then
+ list, first, last, ni, nm = locate(list,first,last,ni,nm)
+ setlist(current,list)
+ end
+ current = getnext(current)
+ elseif migrate_inserts and id == insert_code then
+ local insert
+ head, current, insert = remove_node(head,current)
+ setnext(insert)
+ if first then
+ setlink(last,insert)
+ else
+ setprev(insert)
+ first = insert
+ end
+ last = insert
+ ni = ni + 1
+ elseif migrate_marks and id == mark_code then
+ local mark
+ head, current, mark = remove_node(head,current)
+ setnext(mark)
+ if first then
+ setlink(last,mark)
+ else
+ setprev(mark)
+ first = mark
+ end
+ last = mark
+ nm = nm + 1
+ else
+ current = getnext(current)
+ end
+ end
+ return head, first, last, ni, nm
+end
+
+function nodes.handlers.migrate(head,where)
+ local done = false
+ if head then
+ if trace_migrations then
+ report_nodes("migration sweep %a",where)
+ end
+ local current = tonut(head)
+ while current do
+ local id = getid(current)
+ -- inserts_too is a temp hack, we should only do them when it concerns
+ -- newly placed (flushed) inserts
+ if id == vlist_code or id == hlist_code or (inserts_too and id == insert_code) and not getattr(current,a_migrated) then
+ setattr(current,a_migrated,1)
+ t_sweeps = t_sweeps + 1
+ local h = getlist(current)
+ local first, last, ni, nm
+ while h do
+ local id = getid(h)
+ if id == vlist_code or id == hlist_code then
+ h, first, last, ni, nm = locate(h,first,last,0,0)
+ end
+ h = getnext(h)
+ end
+ if first then
+ t_inserts = t_inserts + ni
+ t_marks = t_marks + nm
+ if trace_migrations and (ni > 0 or nm > 0) then
+ report_nodes("sweep %a, container %a, %s inserts and %s marks migrated outwards during %a",
+ t_sweeps,nodecodes[id],ni,nm,where)
+ end
+ -- inserts after head, use insert_after
+ local n = getnext(current)
+ if n then
+ setlink(last,n)
+ end
+ setlink(current,first)
+ done = true
+ current = last
+ end
+ end
+ current = getnext(next)
+ end
+ return head, done
+ end
+end
+
+-- for the moment this way, this will disappear
+
+experiments.register("marks.migrate", function(v)
+ if v then
+ tasks.enableaction("mvlbuilders", "nodes.handlers.migrate")
+ end
+ migrate_marks = v
+end)
+
+experiments.register("inserts.migrate", function(v)
+ if v then
+ tasks.enableaction("mvlbuilders", "nodes.handlers.migrate")
+ end
+ migrate_inserts = v
+end)
+
+experiments.register("inserts.migrate.nested", function(v)
+ if v then
+ tasks.enableaction("mvlbuilders", "nodes.handlers.migrate")
+ end
+ inserts_too = 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)