Testing Generic Tuple and Path Structuring

Generic TUPLE! and PATH! are fairly similar. Both are immutable types, both have to have at least two elements, and neither allow nesting into themselves. So you can't put a tuple-into-a-tuple or a path-into-a-path.

But you can put a tuple in a path...just not vice versa. So a.b.c/d.e.f is a 2-element PATH! containing two 3-element TUPLE!. While a/b/c.d/e/f is a 5-element PATH! whose third element is a TUPLE!.

Writing this is complicated, especially because the scanner is kind of "ad hoc" and has been evolving organically over time. So I came up with an interesting test dialect.

Structural Equivalence Testing

Here are the two examples above shown in the test dialect. Each line contains a string, an arrow, and then one or more isomorphic structures, where PATH! is replaced with BLOCK! and TUPLE! is replaced with GROUP!:

"a.b.c/d.e.f"  ->  [(a b c) (d e f)]
"a/b/c.d/e/f"  ->  [a b (c d) e f]

So then what the test does is LOAD the string, and transform its paths and tuples into the blocks and groups on the right of the arrow.

Because actual BLOCK! and GROUP!s are legal in tuples and paths, the transformation turns them into ^block and ^group in the tests that use them:

"[a].(b)"  ->  (^[a] ^(b))

Whitespace testing is important, to make sure it reacts correctly...which means you can get more than one value on the right:

"(a b)/c"  ->  [^(a b) c]
"(a b) /c"  ->  ^(a b)  [_ c]

I decided it was a nice use of the NEW-LINE? to detect when a new test started. I still don't know exactly where on balance in dialecting it's good or bad to use line breaks, but it would be much noisier if each test had to be in a BLOCK! or if there had to be some explicit <new-test> tag.

I found that on a page full of tests, two spaces between things helped... and also, the ability to group a few similar tests together and then skip a line before another group of tests:

"."  ->  (_ _)
".."  ->  (_ _ _)
"..."  ->  (_ _ _ _)

"/a"  ->  [_ a] 
"//a"  ->  [_ _ a]
"a/"  ->  [a _]
"a//"  ->  [a _ _]
"/a/"  ->  [_ a _]
"//a//"  ->  [_ _ a _ _]

Anyway, the generic tuple commit is all still a work in progress...but hopefully I'll be able to get it hammered together soon. Some pretty fancy cases are working!

"a.1.(x)/[a b c]/<d>.2"  ->  [(a 1 ^(x)) ^[a b c] (<d> 2)]

"/./(a b)/./"  ->  [_ (_ _) ^(a b) (_ _) _]

But equally important to what kinds of wild paths and tuples you might create if you wanted, is the fact that mysteriously evil paths and tuples won't be able to exist. So don't fear the power... get ready to enjoy the coherence.

2 Likes