I’m no closer to a solution for this, but in case it helps anyone, here’s the routine R_COLLECT_MATCH_ALL which is called at the end of a (determine object) construction. I’ve used approximately Inform 6 syntax since that’s what I’m used to, but with a couple modifications (e.g. indicating explicitly which local variables are parameters and which aren’t).
[ R_COLLECT_MATCH_ALL input / current keywords oldtop iter word tmp ;
oldtop = top; ! `top` is a global that holds the top of the heap (grows upwards)
R_COLLECT_END(keywords);
l2:
input = R_DEREF(input);
tmp = input & $E000;
if(tmp != $C000) jump l3;
current = input - $4000; ! ref to head element
input = current + 1; ! ref to tail element
current = R_DEREF(current);
if(keywords == nil) jump l1;
iter = keywords;
l4:
iter = iter & nil;
word = memory-->iter;
iter = memory-->(iter+1);
tmp = R_WOULD_UNIFY(word, current);
if(tmp) jump l2;
if(iter ~= nil) jump l4;
l1:
@throw fail; ! `fail` is a global holding a throw destination for a predicate failing
l3:
top = oldtop;
if(input ~= nil) jump l1;
rfalse;
];