1if not modules then modules = { } end modules ['node-mig'] = {
2 version = 1.001,
3 comment = "companion to node-mig.mkiv",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9local format = string.format
10
11local trace_migrations = false trackers.register("nodes.migrations", function(v) trace_migrations = v end)
12
13local report_nodes = logs.reporter("nodes","migrations")
14
15local attributes = attributes
16local nodes = nodes
17
18local nuts = nodes.nuts
19local tonut = nuts.tonut
20
21local getnext = nuts.getnext
22local getid = nuts.getid
23local getlist = nuts.getlist
24local getprop = nuts.getprop
25
26local setprop = nuts.setprop
27local setlink = nuts.setlink
28local setlist = nuts.setlist
29local setprev = nuts.setprev
30local setnext = nuts.setnext
31local setboth = nuts.setboth
32
33local remove_node = nuts.remove
34local count = nuts.count
35
36local nodecodes = nodes.nodecodes
37local hlist_code = nodecodes.hlist
38local vlist_code = nodecodes.vlist
39local insert_code = nodecodes.ins
40local mark_code = nodecodes.mark
41
42local a_migrated = attributes.private("migrated")
43local trialtypesetting = context.trialtypesetting
44
45local migrate_inserts = false
46local migrate_marks = false
47
48local t_inserts = 0
49local t_marks = 0
50local t_sweeps = 0
51
52local function locate(head,first,last)
53 local current = head
54 while current do
55 local id = getid(current)
56 if id == vlist_code or id == hlist_code then
57 local list = getlist(current)
58 if list then
59 local l
60 l, first, last = locate(list,first,last)
61 if l ~= list then
62 setlist(current,l)
63 end
64 end
65 current = getnext(current)
66 elseif id == insert_code then
67 if migrate_inserts then
68 local insert
69 head, current, insert = remove_node(head,current)
70 if first then
71 setnext(insert)
72 setlink(last,insert)
73 else
74 setboth(insert)
75 first = insert
76 end
77 last = insert
78 end
79 elseif id == mark_code then
80 if migrate_marks then
81 local mark
82 head, current, mark = remove_node(head,current)
83 if first then
84 setnext(mark)
85 setlink(last,mark)
86 else
87 setboth(mark)
88 first = mark
89 end
90 last = mark
91 end
92 else
93 current = getnext(current)
94 end
95 end
96 return head, first, last
97end
98
99function nodes.handlers.migrate(head,where)
100 if head and not trialtypesetting() then
101 if trace_migrations then
102 report_nodes("migration sweep %a",where)
103 end
104 local current = head
105 while current do
106 local id = getid(current)
107 if (id == vlist_code or id == hlist_code or id == insert_code) and not getprop(current,"migrated") then
108 setprop(current,"migrated",true)
109 local h = getlist(current)
110 if h then
111 t_sweeps = t_sweeps + 1
112 local first, last
113 while h do
114 local id = getid(h)
115 if id == vlist_code or id == hlist_code then
116 h, first, last = locate(h,first,last)
117 end
118 h = getnext(h)
119 end
120 if first then
121 if trace_migrations then
122 local ni = count(insert_code,first)
123 local nm = count(mark_code,first)
124 t_inserts = t_inserts + ni
125 t_marks = t_marks + nm
126 report_nodes("sweep %a, container %a, %s inserts and %s marks migrated outwards during %a",
127 t_sweeps,nodecodes[id],ni,nm,where)
128 end
129 local n = getnext(current)
130 if n then
131 setlink(last,n)
132 end
133 setlink(current,first)
134 current = last
135 end
136 end
137 end
138 current = getnext(current)
139 end
140 end
141 return head
142end
143
144statistics.register("node migrations", function()
145 if trace_migrations and t_sweeps > 0 then
146 return format("%s sweeps, %s inserts moved, %s marks moved",t_sweeps,t_inserts,t_marks)
147 end
148end)
149
150
151
152
153
154local enableaction = nodes.tasks.enableaction
155local disableaction = nodes.tasks.disableaction
156
157local migrations = { }
158nodes.migrations = migrations
159local enabled = false
160
161local function check()
162 if migrate_marks or migrate_inserts then
163 if not enabled then
164 enableaction("mvlbuilders", "nodes.handlers.migrate")
165 enableaction("processors", "nodes.handlers.migrate")
166 enabled = true
167 end
168 else
169 if enabled then
170 disableaction("mvlbuilders", "nodes.handlers.migrate")
171 disableaction("processors", "nodes.handlers.migrate")
172 enabled = false
173 end
174 end
175end
176
177function migrations.setmarks(v)
178 migrate_marks = v
179 check()
180end
181
182function migrations.setinserts(v)
183 migrate_inserts = v
184 check()
185end
186 |