Tom Lord <xxxxxx@emf.net> writes:
> /* untested code */
> t_scm_error
> scm_assq (t_scm_word * answer,
> t_scm_arena instance,
> t_scm_word * key,
> t_scm_word * alist)
> {
> struct assq_frame
> {
> SCM_FRAME;
> scm_word_t * pair;
> scm_word_t * key;
> } l;
>
> SCM_PROTECT_FRAME (l);
>
>
> scm_make_false (answer, instance);
>
> while (scm_is_pair (instance, alist))
> {
> scm_car (&l.pair, instance, alist);
> scm_car (&l.key, instance, &l.pair);
> if (scm_values_eq (instance, &l.key, key))
> {
> SCM_LSET (answer, instance, &l.pair);
> break;
> }
> scm_cdr (alist, instance, alist);
> }
>
> SCM_UNPROTECT_FRAME (l);
> return 0;
> }
It's worth noting here that SCM_LSET is essentially a 'linearizing'
assignment operator. I'd been thinking of providing a similar
operator for Minor:
/* Free the reference DEST, if DEST is non-zero; then return SRC.
This is meant to help free a variable's value before assigning
to it:
x = mn_set (c, x, new_value); */
mn_ref *mn_set (mn_call *, mn_ref *dest, mn_ref *src);
If Minor provided an operator like that, then one could write the
Minor example in a very similar fashion to the Pika example:
mn_ref *
assq (mn_call *c, mn_ref *key, mn_ref *alist)
{
mn_ref *pair = 0;
mn_ref *pair_key = 0;
while (mn_pair_p (c, alist))
{
pair = mn_set (c, pair, mn_car (c, alist));
pair_key = mn_set (c, pair_key, mn_car (c, pair));
if (mn_ref_eq (c, key, pair_key))
return pair;
alist = mn_to_cdr (c, alist);
}
return mn_false (c);
}
Here's Tom's code again, for reference:
/* untested code */
t_scm_error
scm_assq (t_scm_word * answer,
t_scm_arena instance,
t_scm_word * key,
t_scm_word * alist)
{
struct assq_frame
{
SCM_FRAME;
scm_word_t * pair;
scm_word_t * key;
} l;
SCM_PROTECT_FRAME (l);
scm_make_false (answer, instance);
while (scm_is_pair (instance, alist))
{
scm_car (&l.pair, instance, alist);
scm_car (&l.key, instance, &l.pair);
if (scm_values_eq (instance, &l.key, key))
{
SCM_LSET (answer, instance, &l.pair);
break;
}
scm_cdr (alist, instance, alist);
}
SCM_UNPROTECT_FRAME (l);
return 0;
}
I think this underscores how fundamentally similar the two are:
- Minor calls correspond to Pika frames.
- Minor heap-allocates while Pika stack-allocates.
I think the biggest difference between the two is that Pika ties
reference lifetimes very tightly to lexical block lifetimes, whereas
Minor binds them to call lifetimes, but allows/requires you to do some
other explicit frees. Each has some advantages and some
disadvantages.