diff options
author | Context Git Mirror Bot <phg42.2a@gmail.com> | 2016-08-01 16:40:14 +0200 |
---|---|---|
committer | Context Git Mirror Bot <phg42.2a@gmail.com> | 2016-08-01 16:40:14 +0200 |
commit | 96f283b0d4f0259b7d7d1c64d1d078c519fc84a6 (patch) | |
tree | e9673071aa75f22fee32d701d05f1fdc443ce09c /doc/context/sources/general/manuals/about/about-properties.tex | |
parent | c44a9d2f89620e439f335029689e7f0dff9516b7 (diff) | |
download | context-96f283b0d4f0259b7d7d1c64d1d078c519fc84a6.tar.gz |
2016-08-01 14:21:00
Diffstat (limited to 'doc/context/sources/general/manuals/about/about-properties.tex')
-rw-r--r-- | doc/context/sources/general/manuals/about/about-properties.tex | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/doc/context/sources/general/manuals/about/about-properties.tex b/doc/context/sources/general/manuals/about/about-properties.tex new file mode 100644 index 000000000..07bb2924c --- /dev/null +++ b/doc/context/sources/general/manuals/about/about-properties.tex @@ -0,0 +1,209 @@ +% language=uk + +\startcomponent about-properties + +\environment about-environment + +\startchapter[title=Properties] + +\startsection[title=Introduction] + +Attributes are a nice extension to \TEX\ as they permits us to let information +travel with nodes. Internally they are represented as a linked list that +travels with a node. Because often a sequence of nodes has the same attributes, +this mechanism is quite efficient. Access is relatively fast too. Attributes +have a number and a value (also a number) which is fine. Of course one could +wish for them to be anything, but imagine the amount of management needed +in the engine if that were the case. Not only does saving and restoring (due to +grouping) at the \TEX\ end has no \LUA\ equivalent, an overload of the \LUA\ +registry (the most natural interface for this) is not what we want. Of course +it is also not acceptable that (future) extensions slow down a run. In fact, +leaner and meaner should be the main objective. + +At some point I thought that packing crucial information in a node using a bitset +would help to speed up some critical mechanisms (mostly fonts) but although +managing some 32 or 64 on||off states is possible in a more closed macro package, +in practice it would lead to conflicts in use. Also, an experimental +implementation of this idea was not faster than using attributes due to the fact +that manipulating bits also involves function calls that deal with setting, +resetting, masking and more. It also makes nodes larger and increases the memory +footprint. + +So, when I discarded that idea, I moved to another one, which is associating a +\LUA\ table with each node (that makes sense). Again, an implementation where +some way a reference to a table is carried with a node, is non||trivial because +it has to go via the \LUA\ registry and will not be too efficient in terms of +speed. Also, when dealing with such information one wants to stay at the \LUA\ +end and not cross the C||boundary too often. + +Therefore a different approach was taken which involves a \LUA\ table. The main +issue with carrying information with a node is not to associate that information, +but to make sure that it gets cleaned up when a node is freed and copied when a +node is copied. All nodes that have attributes, also get properties. + +\stopsection + +\startsection[title=The implementation] + +The implementation is rather minimalistic. This is because hard codes solutions +don't fit in the \LUATEX\ design philosophy. Also, there are many ways to use +such a mechanism so too much hard coded behaviour only complicates usage. + +When a node is copied, we also copy the associated property entry. Normally its +type is \type {nil} or \type {table}. Depending on how you enabled this +mechanism, the table copy is shallow (just a reference to the same table), or we +assign en empty table with the original as metatable index. The second approach +as some more overhead. + +When a new node is assigned, nothing extra is done with the properties. The +overhead is zero. This means that when you want to assign properties at the \LUA\ +end, you also have to check if a node property already has a table and if not, +create one. The same is true for querying properties: you have to test if there +are properties at all. + +When you use the \quote {direct} node model, you can directly access the property +table. But, with direct as well as wrapped nodes, you can also use setters and +getters. The property table has no metatable so you can add your own one for +alternative access if needed. In \CONTEXT\ you can best stay away from such hacks +and use the provided mechanisms because otherwise you get a performance hit. + +\stopsection + +\startsection[title=The \LUA\ interface] + +The interface (in regular nodes as well as direct ones) is quite simple and +provides five functions: + +\starttyping +set_properties_mode(boolean,boolean) +flush_properties_table() +get_properties_table() +getproperty(node_id) +setproperty(node_id,value) +\stoptyping + +By default this mechanism is disabled so that when it's not used, there is no +overhead involved. With \type {set_properties_mode} the first argument determines +if you enable or disable this mechanism. The properties themselves are untouched. +When the second argument is \type {true} copied properties create a new table +with a metatable pointing to the original. You can flush all properties with +\type {flush_properties_table}. + +You can access and set properties with \type {getproperty} and \type +{setproperty}. Instead you can also use the table approach, where you can reach +the table with \type {get_properties_table}. Keep in mind that the normal and +direct calls to this function return a different table. + +\stopsection + +\startsection[title=A few examples] + +The following examples use \CONTEXT\ but apart from the calls to the \type +{context} namespace, they are rather generic. We have enabled the property +mechanism with: + +\starttyping +set_properties_mode(true) +\stoptyping + +We fill a box: + +\startbuffer +\newbox\MyPropertyBox + +\setbox\MyPropertyBox=\hbox{test} +\stopbuffer + +\typebuffer \getbuffer + +\startbuffer[common] +local list = tex.getbox("MyPropertyBox").list + +local function start() + context.starttabulate { "||||" } + context.HL() +end + +local function stop() + context.HL() + context.stoptabulate() +end + +local function row(n,p) + context.NC() context(tostring(n==p)) + context.NC() context(tostring(n)) + context.NC() context(tostring(p)) + context.NC() context.NR() +end +\stopbuffer + +\typebuffer[common] + +We will demonstrate the four access models. First regular properties +using functions: + +\startbuffer[example] +for n in node.traverse(list) do + node.setproperty(n,{ vif = n }) +end +start() +for n in node.traverse(list) do + row(n,node.getproperty(n).vif) +end +stop() +\stopbuffer + +\typebuffer[example] {\ttxx\ctxluabuffer[common,example]} + +We can use a table instead (in fact, we can use both approaches +mixed: + +\startbuffer[example] +local n_properties = node.get_properties_table() + +for n in node.traverse(list) do + n_properties[n] = { vit = n } + node.direct.setproperty(n,{ vdf = n }) +end +start() +for n in node.traverse(list) do + row(n,n_properties[n].vit) +end +stop() +\stopbuffer + +\typebuffer[example] {\ttxx\ctxluabuffer[common,example]} + +The direct method looks the same, apart from a cast to direct: + +\startbuffer[example] +for n in node.direct.traverse(node.direct.todirect(list)) do + node.direct.setproperty(n,{ vdf = n }) +end +start() +for n in node.direct.traverse(node.direct.todirect(list)) do + row(n,node.direct.getproperty(n).vdf) +end +stop() +\stopbuffer + +\typebuffer[example] {\tt\ctxluabuffer[common,example]} + +Again, we can use the table approach: + +\startbuffer[example] +local d_properties = node.direct.get_properties_table() + +for n in node.direct.traverse(node.direct.todirect(list)) do + d_properties[n] = { vdt = n } +end +start() +for n in node.direct.traverse(node.direct.todirect(list)) do + row(n,d_properties[n].vdt) +end +stop() +\stopbuffer + +\typebuffer[example] {\tt\ctxluabuffer[common,example]} + +\stoptext |