Today work has focused (again) on two things; Working out some of the details of the ctest extension when it comes to the actual test templates, and simplifying some of the parser logic on the compiler side of things.
The ctest stuff had me reworking the public API that exposes identifiers for the items that we parse from external crates. Previously, I simply returned the whole item path in the ident function, where now I provide both the rust_ident and path functions to yield the full stringified path as well as the last element of that path (the “identifier” proper.)
This change also required that I provide a way of escaping the path separator (::) between path segments when using that string for producing the identifiers of the generated tests. I decided to initially go with escaping those with _ symbols.
I’ve also started changing most places that used the function that now returns the full path and previously returned the path’s last segment with calls into the above escaping function. Some of these, though, require more careful handling as they don’t always need to use that one identifier.
In terms of compiler work, I’ve finished reading through the chapter on Appel’s book I started on yesterday, and have since started refactoring most of the productions in the Menhir rules to fit the changes that my last refactor the supporting OCaml module ended up with.
Chief among these changes is the way I was handling bindings. These can introduced through patterns, which themselves require careful consideration even at parse time. Because I simply cannot resolve the rhs expression to check whether the pattern on the left hand side is refutable, I instead expanded the let-binding data constructor on the expression type constructor with an optional field (as it is an inline record) that takes into consideration binding context.
I then defined the binding context as the rest of the bindings introduced in the pattern, including the binding for which I’m providing a definition. This requires first flattenning the pattern (which I have already a routine for) and recursing through it to introduce new bindings for each named pattern, alongside a copy of the entire (unflattened) pattern.
The right hand side expression I simply keep as the body of the binding in much the same way as I would with the syntax sugar for special function declarations. If during evaluation there is binding context, then I know I ought set expectations on the rhs expression.
Then I also fixed a mistake I made while assuming that type aliases in type equations introduced for GADTs work like they do with plain ADTs. I only realiazed this when I got an error for an existential type while implementing the above pattern flattening routine.
With respect to GADTs, I got rid of some of the ones I was using for expecting any expression or rule, as using anonymous type variables there that are also existential seems like it is too constraining. I know statically all variants and the only reason why I was doing the above was to avoid having a type constructor with only a type equation that gathered the target GADT with all polymorphic variants in a closed matching.
That should let me work out stuff without needlessly worrying about existential types being thrown around between nested recursive functions and locally abstract types (what I initially attempted for the pattern flattenning routine.)
None.
I expect to continue working on the ctest stuff some more as I’m fairly confident the changes thus far are not breaking in so far as I rename the rust_ident routine to ident (and thus fill the hole I left when renaming the latter to path and changing its semantics.) Then the only thing that remains is to work out how should the identifiers for tests be with items in nested modules. I may go the easy route here and just leave everything as-is, while producing multiple test templates for each module.
In terms of compiler work, I expected to go back to implementing the parser today, and that is exactly what I have done. I am fairly satisfied with the outcome of the let-binding data constructor, and I will follow up with whatever tomorrow. There’s always stuff left to do.