node-pro.lmt /size: 5367 b    last modification: 2024-01-16 09:02
1if not modules then modules = { } end modules ['node-pro'] = {
2    version   = 1.001,
3    comment   = "companion to node-ini.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 trace_callbacks  = false  trackers  .register("nodes.callbacks",        function(v) trace_callbacks  = v end)
10local force_processors = false  directives.register("nodes.processors.force", function(v) force_processors = v end)
11
12local report_nodes = logs.reporter("nodes","processors")
13
14local nodes        = nodes
15local tasks        = nodes.tasks
16local nuts         = nodes.nuts
17local tonut        = nodes.tonut
18local tonode       = nodes.tonode
19
20nodes.processors   = nodes.processors or { }
21local processors   = nodes.processors
22
23local tasks        = nodes.tasks
24
25local report_nodes = logs.reporter("nodes","processors")
26
27local countnodes   = nuts.countall
28
29do
30
31    local function reconstruct(head)
32        return ",stream : " .. nodes.listtoutf(head,"",false,nil,true)
33    end
34
35    local before = nil
36    local count  = 0
37    local show   = false
38
39    function processors.trace_glyph_run_b(head,groupcode)
40        count  = count + 1
41        before = countnodes(head)
42    end
43
44    function processors.trace_glyph_run_a(head,groupcode)
45        report_nodes("processors: run %i, group %a, # before %a, # after %s%s",
46            count,groupcode,before,countnodes(head),
47            show and reconstruct(head) or ""
48        )
49        before = false
50    end
51
52    local prependaction = tasks.prependaction
53    local appendaction  = tasks.appendaction
54    local enableaction  = tasks.enableaction
55    local disableaction = tasks.disableaction
56
57    trackers.register("nodes.callbacks", function(v)
58        if not v then
59            disableaction("processors","nodes.processors.trace_glyph_run_b")
60            disableaction("processors","nodes.processors.trace_glyph_run_a")
61        elseif before == nil then
62            prependaction("processors","before","nodes.processors.trace_glyph_run_b",nil,"nonut","enabled")
63            appendaction ("processors","after", "nodes.processors.trace_glyph_run_a",nil,"nonut","enabled")
64            before = false
65        else
66            enableaction("processors","nodes.processors.trace_glyph_run_b")
67            enableaction("processors","nodes.processors.trace_glyph_run_a")
68            show = v == "detail"
69        end
70    end)
71
72end
73
74local glyph_run             = tasks.actions("processors")
75local pre_linebreak_filter  = tasks.actions("paragraphs")
76local post_linebreak_filter = tasks.actions("finalizers")
77
78processors.glyph_run             = glyph_run
79processors.pre_linebreak_filter  = pre_linebreak_filter
80processors.post_linebreak_filter = post_linebreak_filter
81
82callbacks.register("glyph_run",            glyph_run,            "glyph processing")
83callbacks.register("pre_linebreak_filter", pre_linebreak_filter, "horizontal manipulations (before par break)")
84callbacks.register("post_linebreak_filter",post_linebreak_filter,"horizontal manipulations (after par break)")
85
86do
87    local hpack = nodes.hpack
88
89    function nodes.fullhpack(head,...)
90        return hpack((glyph_run(head)),...)
91    end
92
93    local hpack = nuts.hpack
94
95    function nuts.fullhpack(head,...)
96        return hpack(tonut(glyph_run(tonode(head))),...)
97    end
98end
99
100do
101
102    ----- texnest       = tex.nest
103    ----- getnest       = tex.getnest
104
105    local getlist       = nodes.getlist     -- still nodes !
106    local setlist       = nodes.setlist
107    local getsubtype    = nodes.getsubtype
108
109    local linelist_code = nodes.listcodes.line
110
111    local lineactions   = tasks.actions("contributers")
112    local adjustactions = tasks.actions("adjusters")
113
114    -- this was the "contributers" callback but we changed the interface
115
116    -- historically we use a different order than the callback
117
118    function processors.append_line_filter(head,tail,where,index)
119        if tail then
120            if where == "box" then
121                -- here we don't return something, we operate on the line (content)
122                if getsubtype(tail) == linelist_code then -- always
123                    local list = getlist(tail)
124                    if list then
125                        local result = lineactions(list,where,tail,index) -- tail is parent of list
126                        if result and result ~= list then
127                            setlist(tail,result)
128                        end
129                    end
130                end
131            elseif where == "postadjust" or where == "preadjust" then
132                -- we use the same order as for lines
133                return adjustactions(head,where,tail,index)
134            end
135        end
136    end
137
138    callbacks.register("append_line_filter", processors.append_line_filter, "things done with lines")
139
140end
141
142do
143
144    local actions = tasks.actions("alignments")
145
146    function processors.alignment_filter(head,where,callback,attr,preamble)
147        -- todo: add timing
148        if callback then
149            actions(head,where,callback,attr,preamble)
150        end
151    end
152
153    callbacks.register("alignment_filter", processors.alignment_filter, "things done with alignments")
154
155end
156
157statistics.register("h-node processing time", function()
158    return statistics.elapsedseconds(nodes,"including kernel") -- hm, ok here?
159end)
160