diff options
Diffstat (limited to 'tex/context/base/node-ini.lua')
-rw-r--r-- | tex/context/base/node-ini.lua | 842 |
1 files changed, 421 insertions, 421 deletions
diff --git a/tex/context/base/node-ini.lua b/tex/context/base/node-ini.lua index 1de6fbddd..5a3986c3a 100644 --- a/tex/context/base/node-ini.lua +++ b/tex/context/base/node-ini.lua @@ -1,421 +1,421 @@ -if not modules then modules = { } end modules ['node-ini'] = {
- version = 1.001,
- comment = "companion to node-ini.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
---[[ldx--
-<p>Most of the code that had accumulated here is now separated in
-modules.</p>
---ldx]]--
-
--- this module is being reconstructed
-
-local next, type = next, type
-local format, match, gsub = string.format, string.match, string.gsub
-local concat, remove = table.concat, table.remove
-local sortedhash, sortedkeys, swapped, tohash = table.sortedhash, table.sortedkeys, table.swapped, table.tohash
-local utfchar = utf.char
-local lpegmatch = lpeg.match
-local formatcolumns = utilities.formatters.formatcolumns
-
---[[ldx--
-<p>Access to nodes is what gives <l n='luatex'/> its power. Here we
-implement a few helper functions. These functions are rather optimized.</p>
---ldx]]--
-
---[[ldx--
-<p>When manipulating node lists in <l n='context'/>, we will remove
-nodes and insert new ones. While node access was implemented, we did
-quite some experiments in order to find out if manipulating nodes
-in <l n='lua'/> was feasible from the perspective of performance.</p>
-
-<p>First of all, we noticed that the bottleneck is more with excessive
-callbacks (some gets called very often) and the conversion from and to
-<l n='tex'/>'s datastructures. However, at the <l n='lua'/> end, we
-found that inserting and deleting nodes in a table could become a
-bottleneck.</p>
-
-<p>This resulted in two special situations in passing nodes back to
-<l n='tex'/>: a table entry with value <type>false</type> is ignored,
-and when instead of a table <type>true</type> is returned, the
-original table is used.</p>
-
-<p>Insertion is handled (at least in <l n='context'/> as follows. When
-we need to insert a node at a certain position, we change the node at
-that position by a dummy node, tagged <type>inline</type> which itself
-has_attribute the original node and one or more new nodes. Before we pass
-back the list we collapse the list. Of course collapsing could be built
-into the <l n='tex'/> engine, but this is a not so natural extension.</p>
-
-<p>When we collapse (something that we only do when really needed), we
-also ignore the empty nodes. [This is obsolete!]</p>
---ldx]]--
-
-local traverse = node.traverse
-local traverse_id = node.traverse_id
-local free_node = node.free
-local remove_node = node.remove
-local insert_node_before = node.insert_before
-local insert_node_after = node.insert_after
-local node_fields = node.fields
-
-local allocate = utilities.storage.allocate
-
-nodes = nodes or { }
-local nodes = nodes
-
-nodes.handlers = nodes.handlers or { }
-
--- there will be more of this:
-
-local skipcodes = allocate {
- [ 0] = "userskip",
- [ 1] = "lineskip",
- [ 2] = "baselineskip",
- [ 3] = "parskip",
- [ 4] = "abovedisplayskip",
- [ 5] = "belowdisplayskip",
- [ 6] = "abovedisplayshortskip",
- [ 7] = "belowdisplayshortskip",
- [ 8] = "leftskip",
- [ 9] = "rightskip",
- [ 10] = "topskip",
- [ 11] = "splittopskip",
- [ 12] = "tabskip",
- [ 13] = "spaceskip",
- [ 14] = "xspaceskip",
- [ 15] = "parfillskip",
- [ 16] = "thinmuskip",
- [ 17] = "medmuskip",
- [ 18] = "thickmuskip",
- [100] = "leaders",
- [101] = "cleaders",
- [102] = "xleaders",
- [103] = "gleaders",
-}
-
-local penaltycodes = allocate { -- unfortunately not used
- [ 0] = "userpenalty",
-}
-
-table.setmetatableindex(penaltycodes,function(t,k) return "userpenalty" end) -- not used anyway
-
-local noadcodes = allocate {
- [ 0] = "ord",
- [ 1] = "opdisplaylimits",
- [ 2] = "oplimits",
- [ 3] = "opnolimits",
- [ 4] = "bin",
- [ 5] = "rel",
- [ 6] = "open",
- [ 7] = "close",
- [ 8] = "punct",
- [ 9] = "inner",
- [10] = "under",
- [11] = "over",
- [12] = "vcenter",
-}
-
-local listcodes = allocate {
- [ 0] = "unknown",
- [ 1] = "line",
- [ 2] = "box",
- [ 3] = "indent",
- [ 4] = "alignment", -- row or column
- [ 5] = "cell",
-}
-
-local glyphcodes = allocate {
- [0] = "character",
- [1] = "glyph",
- [2] = "ligature",
- [3] = "ghost",
- [4] = "left",
- [5] = "right",
-}
-
-local kerncodes = allocate {
- [0] = "fontkern",
- [1] = "userkern",
- [2] = "accentkern",
-}
-
-local mathcodes = allocate {
- [0] = "beginmath",
- [1] = "endmath",
-}
-
-local fillcodes = allocate {
- [0] = "stretch",
- [1] = "fi",
- [2] = "fil",
- [3] = "fill",
- [4] = "filll",
-}
-
-local margincodes = allocate {
- [0] = "left",
- [1] = "right",
-}
-
-local disccodes = allocate {
- [0] = "discretionary", -- \discretionary
- [1] = "explicit", -- \-
- [2] = "automatic", -- following a -
- [3] = "regular", -- simple
- [4] = "first", -- hard first item
- [5] = "second", -- hard second item
-}
-
-local function simplified(t)
- local r = { }
- for k, v in next, t do
- r[k] = gsub(v,"_","")
- end
- return r
-end
-
-local nodecodes = simplified(node.types())
-local whatcodes = simplified(node.whatsits())
-
-skipcodes = allocate(swapped(skipcodes,skipcodes))
-noadcodes = allocate(swapped(noadcodes,noadcodes))
-nodecodes = allocate(swapped(nodecodes,nodecodes))
-whatcodes = allocate(swapped(whatcodes,whatcodes))
-listcodes = allocate(swapped(listcodes,listcodes))
-glyphcodes = allocate(swapped(glyphcodes,glyphcodes))
-kerncodes = allocate(swapped(kerncodes,kerncodes))
-penaltycodes = allocate(swapped(penaltycodes,penaltycodes))
-mathcodes = allocate(swapped(mathcodes,mathcodes))
-fillcodes = allocate(swapped(fillcodes,fillcodes))
-margincodes = allocate(swapped(margincodes,margincodes))
-disccodes = allocate(swapped(disccodes,disccodes))
-
-nodes.skipcodes = skipcodes nodes.gluecodes = skipcodes -- more official
-nodes.noadcodes = noadcodes
-nodes.nodecodes = nodecodes
-nodes.whatcodes = whatcodes nodes.whatsitcodes = whatcodes -- more official
-nodes.listcodes = listcodes
-nodes.glyphcodes = glyphcodes
-nodes.kerncodes = kerncodes
-nodes.penaltycodes = kerncodes
-nodes.mathcodes = mathcodes
-nodes.fillcodes = fillcodes
-nodes.margincodes = margincodes
-nodes.disccodes = disccodes nodes.discretionarycodes = disccodes
-
-listcodes.row = listcodes.alignment
-listcodes.column = listcodes.alignment
-
-kerncodes.italiccorrection = kerncodes.userkern
-kerncodes.kerning = kerncodes.fontkern
-
-nodes.codes = allocate { -- mostly for listing
- glue = skipcodes,
- noad = noadcodes,
- node = nodecodes,
- hlist = listcodes,
- vlist = listcodes,
- glyph = glyphcodes,
- kern = kerncodes,
- penalty = penaltycodes,
- math = mathnodes,
- fill = fillcodes,
- margin = margincodes,
- disc = disccodes,
- whatsit = whatcodes,
-}
-
-local report_codes = logs.reporter("nodes","codes")
-
-function nodes.showcodes()
- local t = { }
- for name, codes in sortedhash(nodes.codes) do
- local sorted = sortedkeys(codes)
- for i=1,#sorted do
- local s = sorted[i]
- if type(s) ~= "number" then
- t[#t+1] = { name, s, codes[s] }
- end
- end
- end
- formatcolumns(t)
- for k=1,#t do
- report_codes (t[k])
- end
-end
-
-local whatsit_node = nodecodes.whatsit
-
-local messyhack = tohash { -- temporary solution
- nodecodes.attributelist,
- nodecodes.attribute,
- nodecodes.gluespec,
- nodecodes.action,
-}
-
-function nodes.fields(n)
- local id = n.id
- if id == whatsit_node then
- return node_fields(id,n.subtype)
- else
- local t = node_fields(id)
- if messyhack[id] then
- for i=1,#t do
- if t[i] == "subtype" then
- remove(t,i)
- break
- end
- end
- end
- return t
- end
-end
-
-trackers.register("system.showcodes", nodes.showcodes)
-
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
-local glue_code = nodecodes.glue
-
--- if t.id == glue_code then
--- local s = t.spec
--- print(t)
--- print(s,s and s.writable)
--- if s and s.writable then
--- free_node(s)
--- end
--- t.spec = nil
--- end
-
-local function remove(head, current, free_too)
- local t = current
- head, current = remove_node(head,current)
- if t then
- if free_too then
- free_node(t)
- t = nil
- else
- t.next = nil
- t.prev = nil
- end
- end
- return head, current, t
-end
-
-nodes.remove = remove
-
-function nodes.delete(head,current)
- return remove(head,current,true)
-end
-
-nodes.before = insert_node_before
-nodes.after = insert_node_after
-
--- we need to test this, as it might be fixed now
-
-function nodes.before(h,c,n)
- if c then
- if c == h then
- n.next = h
- n.prev = nil
- h.prev = n
- else
- local cp = c.prev
- n.next = c
- n.prev = cp
- if cp then
- cp.next = n
- end
- c.prev = n
- return h, n
- end
- end
- return n, n
-end
-
-function nodes.after(h,c,n)
- if c then
- local cn = c.next
- if cn then
- n.next = cn
- cn.prev = n
- else
- n.next = nil
- end
- c.next = n
- n.prev = c
- return h, n
- end
- return n, n
-end
-
--- local h, c = nodes.replace(head,current,new)
--- local c = nodes.replace(false,current,new)
--- local c = nodes.replace(current,new)
-
-function nodes.replace(head,current,new) -- no head returned if false
- if not new then
- head, current, new = false, head, current
- end
- local prev, next = current.prev, current.next
- if next then
- new.next = next
- next.prev = new
- end
- if prev then
- new.prev = prev
- prev.next = new
- end
- if head then
- if head == current then
- head = new
- end
- free_node(current)
- return head, new
- else
- free_node(current)
- return new
- end
-end
-
--- will move
-
-local function count(stack,flat)
- local n = 0
- while stack do
- local id = stack.id
- if not flat and id == hlist_code or id == vlist_code then
- local list = stack.list
- if list then
- n = n + 1 + count(list) -- self counts too
- else
- n = n + 1
- end
- else
- n = n + 1
- end
- stack = stack.next
- end
- return n
-end
-
-nodes.count = count
-
-local left, space = lpeg.P("<"), lpeg.P(" ")
-
-local reference = left * (1-left)^0 * left * space^0 * lpeg.C((1-space)^0)
-
-function nodes.reference(n)
- return lpegmatch(reference,tostring(n))
-end
-
-if not node.next then
-
- function node.next(n) return n and n.next end
- function node.prev(n) return n and n.prev end
-
-end
+if not modules then modules = { } end modules ['node-ini'] = { + version = 1.001, + comment = "companion to node-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +--[[ldx-- +<p>Most of the code that had accumulated here is now separated in +modules.</p> +--ldx]]-- + +-- this module is being reconstructed + +local next, type = next, type +local format, match, gsub = string.format, string.match, string.gsub +local concat, remove = table.concat, table.remove +local sortedhash, sortedkeys, swapped, tohash = table.sortedhash, table.sortedkeys, table.swapped, table.tohash +local utfchar = utf.char +local lpegmatch = lpeg.match +local formatcolumns = utilities.formatters.formatcolumns + +--[[ldx-- +<p>Access to nodes is what gives <l n='luatex'/> its power. Here we +implement a few helper functions. These functions are rather optimized.</p> +--ldx]]-- + +--[[ldx-- +<p>When manipulating node lists in <l n='context'/>, we will remove +nodes and insert new ones. While node access was implemented, we did +quite some experiments in order to find out if manipulating nodes +in <l n='lua'/> was feasible from the perspective of performance.</p> + +<p>First of all, we noticed that the bottleneck is more with excessive +callbacks (some gets called very often) and the conversion from and to +<l n='tex'/>'s datastructures. However, at the <l n='lua'/> end, we +found that inserting and deleting nodes in a table could become a +bottleneck.</p> + +<p>This resulted in two special situations in passing nodes back to +<l n='tex'/>: a table entry with value <type>false</type> is ignored, +and when instead of a table <type>true</type> is returned, the +original table is used.</p> + +<p>Insertion is handled (at least in <l n='context'/> as follows. When +we need to insert a node at a certain position, we change the node at +that position by a dummy node, tagged <type>inline</type> which itself +has_attribute the original node and one or more new nodes. Before we pass +back the list we collapse the list. Of course collapsing could be built +into the <l n='tex'/> engine, but this is a not so natural extension.</p> + +<p>When we collapse (something that we only do when really needed), we +also ignore the empty nodes. [This is obsolete!]</p> +--ldx]]-- + +local traverse = node.traverse +local traverse_id = node.traverse_id +local free_node = node.free +local remove_node = node.remove +local insert_node_before = node.insert_before +local insert_node_after = node.insert_after +local node_fields = node.fields + +local allocate = utilities.storage.allocate + +nodes = nodes or { } +local nodes = nodes + +nodes.handlers = nodes.handlers or { } + +-- there will be more of this: + +local skipcodes = allocate { + [ 0] = "userskip", + [ 1] = "lineskip", + [ 2] = "baselineskip", + [ 3] = "parskip", + [ 4] = "abovedisplayskip", + [ 5] = "belowdisplayskip", + [ 6] = "abovedisplayshortskip", + [ 7] = "belowdisplayshortskip", + [ 8] = "leftskip", + [ 9] = "rightskip", + [ 10] = "topskip", + [ 11] = "splittopskip", + [ 12] = "tabskip", + [ 13] = "spaceskip", + [ 14] = "xspaceskip", + [ 15] = "parfillskip", + [ 16] = "thinmuskip", + [ 17] = "medmuskip", + [ 18] = "thickmuskip", + [100] = "leaders", + [101] = "cleaders", + [102] = "xleaders", + [103] = "gleaders", +} + +local penaltycodes = allocate { -- unfortunately not used + [ 0] = "userpenalty", +} + +table.setmetatableindex(penaltycodes,function(t,k) return "userpenalty" end) -- not used anyway + +local noadcodes = allocate { + [ 0] = "ord", + [ 1] = "opdisplaylimits", + [ 2] = "oplimits", + [ 3] = "opnolimits", + [ 4] = "bin", + [ 5] = "rel", + [ 6] = "open", + [ 7] = "close", + [ 8] = "punct", + [ 9] = "inner", + [10] = "under", + [11] = "over", + [12] = "vcenter", +} + +local listcodes = allocate { + [ 0] = "unknown", + [ 1] = "line", + [ 2] = "box", + [ 3] = "indent", + [ 4] = "alignment", -- row or column + [ 5] = "cell", +} + +local glyphcodes = allocate { + [0] = "character", + [1] = "glyph", + [2] = "ligature", + [3] = "ghost", + [4] = "left", + [5] = "right", +} + +local kerncodes = allocate { + [0] = "fontkern", + [1] = "userkern", + [2] = "accentkern", +} + +local mathcodes = allocate { + [0] = "beginmath", + [1] = "endmath", +} + +local fillcodes = allocate { + [0] = "stretch", + [1] = "fi", + [2] = "fil", + [3] = "fill", + [4] = "filll", +} + +local margincodes = allocate { + [0] = "left", + [1] = "right", +} + +local disccodes = allocate { + [0] = "discretionary", -- \discretionary + [1] = "explicit", -- \- + [2] = "automatic", -- following a - + [3] = "regular", -- simple + [4] = "first", -- hard first item + [5] = "second", -- hard second item +} + +local function simplified(t) + local r = { } + for k, v in next, t do + r[k] = gsub(v,"_","") + end + return r +end + +local nodecodes = simplified(node.types()) +local whatcodes = simplified(node.whatsits()) + +skipcodes = allocate(swapped(skipcodes,skipcodes)) +noadcodes = allocate(swapped(noadcodes,noadcodes)) +nodecodes = allocate(swapped(nodecodes,nodecodes)) +whatcodes = allocate(swapped(whatcodes,whatcodes)) +listcodes = allocate(swapped(listcodes,listcodes)) +glyphcodes = allocate(swapped(glyphcodes,glyphcodes)) +kerncodes = allocate(swapped(kerncodes,kerncodes)) +penaltycodes = allocate(swapped(penaltycodes,penaltycodes)) +mathcodes = allocate(swapped(mathcodes,mathcodes)) +fillcodes = allocate(swapped(fillcodes,fillcodes)) +margincodes = allocate(swapped(margincodes,margincodes)) +disccodes = allocate(swapped(disccodes,disccodes)) + +nodes.skipcodes = skipcodes nodes.gluecodes = skipcodes -- more official +nodes.noadcodes = noadcodes +nodes.nodecodes = nodecodes +nodes.whatcodes = whatcodes nodes.whatsitcodes = whatcodes -- more official +nodes.listcodes = listcodes +nodes.glyphcodes = glyphcodes +nodes.kerncodes = kerncodes +nodes.penaltycodes = kerncodes +nodes.mathcodes = mathcodes +nodes.fillcodes = fillcodes +nodes.margincodes = margincodes +nodes.disccodes = disccodes nodes.discretionarycodes = disccodes + +listcodes.row = listcodes.alignment +listcodes.column = listcodes.alignment + +kerncodes.italiccorrection = kerncodes.userkern +kerncodes.kerning = kerncodes.fontkern + +nodes.codes = allocate { -- mostly for listing + glue = skipcodes, + noad = noadcodes, + node = nodecodes, + hlist = listcodes, + vlist = listcodes, + glyph = glyphcodes, + kern = kerncodes, + penalty = penaltycodes, + math = mathnodes, + fill = fillcodes, + margin = margincodes, + disc = disccodes, + whatsit = whatcodes, +} + +local report_codes = logs.reporter("nodes","codes") + +function nodes.showcodes() + local t = { } + for name, codes in sortedhash(nodes.codes) do + local sorted = sortedkeys(codes) + for i=1,#sorted do + local s = sorted[i] + if type(s) ~= "number" then + t[#t+1] = { name, s, codes[s] } + end + end + end + formatcolumns(t) + for k=1,#t do + report_codes (t[k]) + end +end + +local whatsit_node = nodecodes.whatsit + +local messyhack = tohash { -- temporary solution + nodecodes.attributelist, + nodecodes.attribute, + nodecodes.gluespec, + nodecodes.action, +} + +function nodes.fields(n) + local id = n.id + if id == whatsit_node then + return node_fields(id,n.subtype) + else + local t = node_fields(id) + if messyhack[id] then + for i=1,#t do + if t[i] == "subtype" then + remove(t,i) + break + end + end + end + return t + end +end + +trackers.register("system.showcodes", nodes.showcodes) + +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local glue_code = nodecodes.glue + +-- if t.id == glue_code then +-- local s = t.spec +-- print(t) +-- print(s,s and s.writable) +-- if s and s.writable then +-- free_node(s) +-- end +-- t.spec = nil +-- end + +local function remove(head, current, free_too) + local t = current + head, current = remove_node(head,current) + if t then + if free_too then + free_node(t) + t = nil + else + t.next = nil + t.prev = nil + end + end + return head, current, t +end + +nodes.remove = remove + +function nodes.delete(head,current) + return remove(head,current,true) +end + +nodes.before = insert_node_before +nodes.after = insert_node_after + +-- we need to test this, as it might be fixed now + +function nodes.before(h,c,n) + if c then + if c == h then + n.next = h + n.prev = nil + h.prev = n + else + local cp = c.prev + n.next = c + n.prev = cp + if cp then + cp.next = n + end + c.prev = n + return h, n + end + end + return n, n +end + +function nodes.after(h,c,n) + if c then + local cn = c.next + if cn then + n.next = cn + cn.prev = n + else + n.next = nil + end + c.next = n + n.prev = c + return h, n + end + return n, n +end + +-- local h, c = nodes.replace(head,current,new) +-- local c = nodes.replace(false,current,new) +-- local c = nodes.replace(current,new) + +function nodes.replace(head,current,new) -- no head returned if false + if not new then + head, current, new = false, head, current + end + local prev, next = current.prev, current.next + if next then + new.next = next + next.prev = new + end + if prev then + new.prev = prev + prev.next = new + end + if head then + if head == current then + head = new + end + free_node(current) + return head, new + else + free_node(current) + return new + end +end + +-- will move + +local function count(stack,flat) + local n = 0 + while stack do + local id = stack.id + if not flat and id == hlist_code or id == vlist_code then + local list = stack.list + if list then + n = n + 1 + count(list) -- self counts too + else + n = n + 1 + end + else + n = n + 1 + end + stack = stack.next + end + return n +end + +nodes.count = count + +local left, space = lpeg.P("<"), lpeg.P(" ") + +local reference = left * (1-left)^0 * left * space^0 * lpeg.C((1-space)^0) + +function nodes.reference(n) + return lpegmatch(reference,tostring(n)) +end + +if not node.next then + + function node.next(n) return n and n.next end + function node.prev(n) return n and n.prev end + +end |