[augeas-devel] Prototype of square lens

David Lutterkort lutter at redhat.com
Thu Jun 17 15:56:09 UTC 2010


Hi Francis,

On Sat, 2010-05-29 at 17:25 -0400, Francis Giraldeau wrote:
> Here is a small patch that add the new primitive square lens with test.

The square lens is actually a lens combinator, not a primitive lens -
it's closer in nature to things like the star operator and other
combinators, except that they are all handled as syntax in the parser,
not as builtin functions.

In the .aug files, we want to write something like

  let s = square re l

so that 'square re l' behaves like 'key re . l . del k k' where k is
whatever was matched by the 'key re' lens.

There's a few steps you need to go through to make that happen:

(1) Add the function glue to builtin.c. That should be a function like

    struct value *lns_square(struct info *, struct value *rxp, struct value *lns)

The function needs to unpack the values and call into a new constructor
lns_make_square in lens.c, similar to lns_make_star. It also needs to
add that glue function to the interpreter with
    DEFINE_NATIVE(modl, "square",  2, lns_square, T_REGEXP, T_LENS, T_LENS);

(2) Add a constructor lns_make_square to lens.c. These functions have
two responsibilities: (i) set up the data structures for a lens and (ii)
set up the types for the lens and typecheck it if it is a nonrecursive
lens

To keep things relatively simple, you can build the square lens up from
existing parts. I'd store it by building a tree of lenses like so:

                       L_SQUARE
                          |   (child pointer)
                       L_CONCAT
                          |   (children pointers)
              +-----------+--------------+
              |           |              |

            L_KEY         l             L_DEL
       with regexp = re              with regexp = re
                                          string = NULL

With this setup, the changes to the get and put functions will be
minimal, especially typechecking will work for free, and there should be
no headaches when l is a recursive lens. You will need to go through the
code and make sure that it still works for L_DEL lenses with a NULL
string (should only be an issue in lns_make_prim and in create_del in
put.c)

(3) Write get_square and parse_square

These functions can get by with doing very little. get_square will look
something like

        static struct tree *get_square(struct lens *lens, struct state *state) {
          struct tree *tree = NULL;
          struct lens *concat = lens->child;
          uint keyreg, delreg;
        
          tree = get_concat(concat, state);
          keyreg = state->nreg + 1;
          delreg = keyreg + (1 + regexp_nsub(concat->children[0]->ctype)) + 1;
          /* Check that the matches in registers keyreg and delreg are identical
             otherwise report an error */
        }

parse_square is completely analogous.

(4) Write put_square and create_square

They should both just pass lens->child to put_concat and create_concat.
To make that work, you need to modify create_del so that it prints out
state->key when lens->string->str is NULL.

There's also lots of places where you need to add L_SQUARE to switch
statements throughout the code (including jmt.c) Those should only
require that you call the same function again with lens->child; for
example, in conv_rhs in jmt.c, you need to add something like

        case L_SQUARE:
        	conv(jmt, lens->child, &s, &e, &f);
        	break;

to the switch statement.

(5) Tests

Write basic tests in a file tests/modules/pass_square.aug. They should
test that 'square re l' works for both non-recursive and recursive l,
and that a square lens can be used inside another recursive lens. The
main point of these tests is to exercise the interpreter, rather than do
anything useful.

Of course, it would also be great to have a working lens that uses
square; a lens that handles XML in general would be a great addition ;)

Let me know if you get stuck with any of the above - there are lots of
subtle details in the code that might throw you off course.

David





More information about the augeas-devel mailing list