3 ms·
I implemented a rather nice C++ pattern matching facility for productions of context-free grammars in my undergraduate thesis project (http://www.grailplus.org
by k4st 16y ago
I implemented a rather nice C++ pattern matching facility for productions of context-free grammars in my undergraduate thesis project (http://www.grailplus.org http://www.grailplus.org). It is able to do some really fancy stuff and I think that is one were using C++ then one could use some similar techniques for creating list comprehensions. Here's how I envision it working:
First, the variables used in the comprehension would be defined locally, with the right types.
Second, we would need an overloaded template function, named something like "constructor" to abstractly represent a constructor for some arbitrary object. Here is how the constructor function works: for N arguments, all taken by reference, it allocates an array of N void * pointers (or sufficiently large slot sizes + proper alignment to hold any pointer type), and returns a pointer to the first slot in that array as some member in an instantiated template, where one of the parameters of the template contains all the info of the types of the constructor parameters. It also initializes each slot of the array to be the address of the local variable passed in to the constructor function by reference. So, if the following is my setup:
int foo;
float bar;
constructor<std::pair>(foo, bar)
returns an object of type Constructor<std::pair, Slot<Base<int>,float> >, where the object contains a pointer to the first slot in the array. This type and the array contain all the info we need to construct an std::pair<int,float>.
The comprehensions would likely require an new iteration mechanism. This was the case in my thesis project, as a cursor-based iterator, while being able to represent the iteration aspect of this, is unable to fully represent the pattern-matching/destructuring bind operations. The tricky part is to make it so that one can advance multiple loops in sequence.
When we know that we can enter the body of the inner loop that would normally represent the innermost loop in an imperative implementation of the same operation being performed by the comprehension then we can use the pointer table to bind values to local variables, and then use a compile-time created function from the Constructor type to yank out those values all at once, impose the proper types using a cast on the void * pointers, and then construct the thing we want to add into our final list.