node-mig.lmt /size: 4328 b    last modification: 2023-12-21 09:44
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 getpost          = nuts.getpost
25local getprop          = nuts.getprop
26
27local setprop          = nuts.setprop
28local setlink          = nuts.setlink
29local setlist          = nuts.setlist
30local setpost          = nuts.setpost
31
32local count            = nuts.count
33local migrate          = nuts.migrate
34
35local nodecodes        = nodes.nodecodes
36local hlist_code       = nodecodes.hlist
37local vlist_code       = nodecodes.vlist
38local insert_code      = nodecodes.ins
39local mark_code        = nodecodes.mark
40
41local a_migrated       = attributes.private("migrated")
42
43local migrate_inserts  = false
44local migrate_marks    = false
45local t_inserts        = 0
46local t_marks          = 0
47local t_sweeps         = 0
48
49local trialtypesetting = context.trialtypesetting
50
51function nodes.handlers.migrate(head,where)
52    -- is this still needed
53    if head and not trialtypesetting() and where == "alignment" then
54        if trace_migrations then
55            report_nodes("migration sweep %a",where)
56        end
57        local current = head
58        while current do
59            local id = getid(current)
60            if (id == vlist_code or id == hlist_code or id == insert_code) and not getprop(current,"migrated") then
61                setprop(current,"migrated",true)
62                local list = getlist(current)
63                if list then
64                    t_sweeps = t_sweeps + 1
65                    local h, first, last = migrate(list,migrate_inserts,migrate_marks)
66                    if first then
67                        if trace_migrations then
68                            local ni = count(insert_code,first)
69                            local nm = count(mark_code,first)
70                            t_inserts = t_inserts + ni
71                            t_marks   = t_marks   + nm
72                            report_nodes("sweep %a, container %a, %s inserts and %s marks migrated outwards during %a",
73                                t_sweeps,nodecodes[id],ni,nm,where)
74
75                        end
76                        local p, t = getpost(current)
77                        if p then
78                            setlink(t,first)
79                        else
80                            setpost(current,first)
81                        end
82                    end
83                end
84            end
85            current = getnext(current)
86        end
87    end
88    return head
89end
90
91statistics.register("node migrations", function()
92    if trace_migrations and t_sweeps > 0 then
93        return format("%s sweeps, %s inserts moved, %s marks moved",t_sweeps,t_inserts,t_marks)
94    end
95end)
96
97-- Since we started with mkiv we had it as experiment but it is about time
98-- to have a more formal interface .. it's still optional due to possible
99-- side effects.
100
101local enableaction  = nodes.tasks.enableaction
102local disableaction = nodes.tasks.disableaction
103local texsetcount   = tex.setcount
104
105local migrations = { }
106nodes.migrations = migrations
107local enabled    = false
108
109local function check()
110    if migrate_marks or migrate_inserts then
111        if not enabled then
112            enableaction("mvlbuilders", "nodes.handlers.migrate")
113            enabled = true
114            texsetcount("automigrationmode",0xFFFF) -- just all of it
115        end
116    else
117        if enabled then
118            disableaction("mvlbuilders", "nodes.handlers.migrate")
119            enabled = false
120            texsetcount("automigrationmode",0)
121        end
122    end
123end
124
125function migrations.setmarks(v)
126    migrate_marks = v
127    check()
128end
129
130function migrations.setinserts(v)
131    migrate_inserts = v
132    check()
133end
134