mirror of
https://github.com/AdaCore/uwrap.git
synced 2026-02-12 13:06:34 -08:00
253 lines
7.7 KiB
ReStructuredText
253 lines
7.7 KiB
ReStructuredText
Template Commands
|
|
=================
|
|
|
|
Overall Structure
|
|
-----------------
|
|
|
|
Wrap, weave and walk clause allows to perform an operation to a node. This
|
|
operation can be:
|
|
|
|
- Instanciate a template on the current node
|
|
- Update a template instance of the current node
|
|
- Control the remainder of the iteration from that node
|
|
- Execute operations on a node
|
|
|
|
It's written:
|
|
|
|
.. code-block:: text
|
|
|
|
wrap <an optional capture> <a static reference to a template> <parameters>;
|
|
weave <an optional capture> <a static reference to a template> <parameters>;
|
|
walk <an optional capture> <a static reference to a template> <parameters>;
|
|
|
|
or when controlling the iteration:
|
|
|
|
.. code-block:: text
|
|
|
|
# TODO: wrap stop is not implemented
|
|
wrap <over or into or stop>;
|
|
|
|
It can be preceded by an optional match clause which will conditionalize and
|
|
parametrize its execution, or an optional pick clause which will select what
|
|
node it operates on
|
|
|
|
.. code-block:: text
|
|
|
|
match <some expression>
|
|
pick <some epression>
|
|
wrap <some expression>;
|
|
|
|
match <some expression>
|
|
pick <some epression>
|
|
weave <some expression>;
|
|
|
|
match <some expression>
|
|
pick <some epression>
|
|
walk <some expression>;
|
|
|
|
It can stand on its own, in which case it unconditionally operates on ``it``:
|
|
|
|
.. code-block:: text
|
|
|
|
wrap <some expression>
|
|
weave <some expression>;
|
|
|
|
A wrap or a weave clause is always terminating a command, and is always followed
|
|
by a semicolon.
|
|
|
|
Wrapping and Weaving Templates
|
|
------------------------------
|
|
|
|
Templates are static structural references. A given node can only be wrapped
|
|
once by such entity. When trying to apply wrap a second time to the same node
|
|
will the same entity, the command will skip.
|
|
|
|
Recall that commands are applied from bottom to top. In the following sequence:
|
|
|
|
.. code-block:: text
|
|
|
|
match x"A"
|
|
wrap standard.out ("TOP");
|
|
|
|
match x"B"
|
|
wrap standard.out ("BOTTOM");
|
|
|
|
The two commands only contain a wrap clause, wrapping with the
|
|
template standard.out. The second one with the text bottom will be executed
|
|
first. When executing the one above, an association between the template
|
|
``standard.out`` and the current node already exists. As a consequence, the wrap
|
|
command will be skipped. This behavior is the core that allows refinement of
|
|
wrapping sequences. For example:
|
|
|
|
.. code-block:: text
|
|
|
|
wrap standard.out ("THE NAME DOESN'T CONTAIN SPECIFIC PATTERN");
|
|
|
|
match x"A"
|
|
wrap standard.out ("THE NAME CONTAINS A");
|
|
|
|
match x"AB"
|
|
wrap standard.out ("THE NAME CONTAINS AB");
|
|
|
|
Wrapping clauses can be developped to further refine the expected behavior.
|
|
|
|
Weave clauses allow to apply more than once a given template. They will either
|
|
instantiate a template if not associated with the node yet or update its field.
|
|
For example in:
|
|
|
|
.. code-block:: text
|
|
|
|
match x"A"
|
|
weave standard.out ("TOP");
|
|
|
|
match x"A"
|
|
weave standard.out ("BOTTOM");
|
|
|
|
The two commands only contain an unconditional wrap clause, weaving with the
|
|
template standard.out. The second one with the text bottom will be executed
|
|
first. The top one will be executed second and update the template instanciated
|
|
previously. "TOP" will be displayed on the screen.
|
|
|
|
Very often, weaving will actually need to update a value rather than overriding
|
|
it. The `@` references the previous value of a given field, so that if in the
|
|
previous example we want to display both TOP and BOTTOM, we could have:
|
|
|
|
.. code-block:: text
|
|
|
|
match x"A"
|
|
weave standard.out (@ & " TOP");
|
|
|
|
match x"A"
|
|
weave standard.out ("BOTTOM");
|
|
|
|
Weaving does not prevent wrapping even if it's applied first. The following code
|
|
will work the same as the code above even if weave is executed first:
|
|
|
|
.. code-block:: text
|
|
|
|
match x"A"
|
|
wrap standard.out (@ & " TOP");
|
|
|
|
match x"A"
|
|
weave standard.out ("BOTTOM");
|
|
|
|
At the time of its creation, a template instance will execute its sequence of
|
|
commands, if any.
|
|
|
|
Walking over a Template
|
|
-----------------------
|
|
|
|
The `walk` command is similar to `weave` and `wrap` in the sense that it allows
|
|
to execute a template. However, contrary to `weave` and `wrap`, the resulting
|
|
associated instance will not be associated to the original node or stored
|
|
after completion of the operation. For all intent and purposes, it will be lost.
|
|
Unlike wrap and weave which manipulate a template that can only be instantiated
|
|
one on a given node, walk can be called several times on the same node, even
|
|
if that node also have a template instantiation. A template instantiated through
|
|
a walk command does not get scheduled for iteration.
|
|
|
|
Walk can be used when it's useful to factorize a series of commands to be
|
|
executed on a node without the need to remembering that this series of commands
|
|
have been ran or any data that has been manipulated. However, it can lead to
|
|
the creation of other instantiations and has a pointer to its origin.
|
|
|
|
So for example:
|
|
|
|
.. code-block:: text
|
|
|
|
template T1;
|
|
|
|
template T2 do
|
|
pick origin wrap T1 ();
|
|
end;
|
|
|
|
match x"A"
|
|
walk T2 ();
|
|
|
|
Walking over T2 in the command will lead to the creation of an T1 wrapper.
|
|
|
|
Wrapping and weaving Template Instances
|
|
---------------------------------------
|
|
|
|
When wrapping or weaving a template, an actual node is created and associated
|
|
with the iterated node. This template instance node will itself be subject to
|
|
its own iteration which will go through the entire program.
|
|
|
|
That second stage of iteration can be used to create another set of template
|
|
instances, or to further refine the values of the created template,
|
|
using information that may not have been available at first.
|
|
|
|
Updating a template can be done through the self weave syntax, which is similar
|
|
to the weave syntax exept that it doesn't mention a template name. The
|
|
following code for example will provide same result as before:
|
|
|
|
.. code-block:: text
|
|
|
|
match standard.out ()
|
|
weave (@ & " TOP");
|
|
|
|
match "A"
|
|
wrap standard.out ("BOTTOM");
|
|
|
|
Note of the fact that template instances created by weave and wrap clauses will
|
|
themselves be subject to the whole program, wrap clauses not contextualized by
|
|
either a match clause or the scope of a template will result in infinite loops:
|
|
|
|
.. code-block:: text
|
|
|
|
wrap standard.out ("INFINITE LOOP");
|
|
|
|
the above code will first wrap input nodes with standard.out, then wrap the
|
|
resulting standard.out node with another instance of standard.out, and so and
|
|
so forth.
|
|
|
|
TODO: There is a simple way to warn about the above, to implement.
|
|
|
|
Controlling Iteration
|
|
---------------------
|
|
|
|
TODO: wrap stop needs to be implemented.
|
|
|
|
A command is always run within the iteration of either a list or a tree
|
|
structure. In some situation, it's useful to be able to either interup this
|
|
iteration, or in the case of a tree, to skip over the elements. This can be
|
|
controlled with the ``wrap into;``, ``wrap over;`` and ``wrap stop;`` operation.
|
|
|
|
- ``wrap into;`` is the default state. It means that the current iteration will
|
|
look a leaves of the current node.
|
|
- ``wrap over`` will prevents leaves to be analyzed. It is the same as
|
|
``wrap into`` when iterating over a list.
|
|
- ``wrap stop`` interups the current iteration.
|
|
|
|
Only one wrap iteration decision can be taken for a given node in a given
|
|
interation. For example:
|
|
|
|
.. code-block:: text
|
|
|
|
wrap into;
|
|
wrap over;
|
|
|
|
Will always apply wrap over.
|
|
|
|
Wrap decisions are usually taken in conjunction with other commands, for
|
|
example:
|
|
|
|
.. code-block:: text
|
|
|
|
match some_conditions do
|
|
wrap something;
|
|
wrap over; # OK, no need to look below.
|
|
end;
|
|
|
|
By default, the main iteration is controlled. However, in the case of a nested
|
|
iteration introduced by an ``all ()`` extension suffix, the wrapping control
|
|
will apply to that iteration instead, e.g.:
|
|
|
|
.. code-block:: text
|
|
|
|
pick child ().all () do
|
|
match some_condition
|
|
wrap something;
|
|
wrap over; # OK, no need to look below.
|
|
end;
|