| parrotcode: Stack handling routines for Parrot | |
| Contents | C | 

src/stacks.c - Stack handling routines for Parrot

The stack is stored as a linked list of chunks (Stack_Chunk),
where each chunk has room for one entry.

Stack_Chunk_t *new_stackstack->name is used for debugging/error reporting.void mark_stackvoid stack_destroysize_t stack_heightStack_Entry_t *stack_entrydepth >= 0,
return the entry at that depth from the top of the stack,
with 0 being the top entry.
If depth < 0,
then return the entry |depth| entries from the bottom of the stack.
Returns NULL if |depth|  number> of entries in stack.void rotate_entriesN > 0,
the rotation is bubble up,
so the top most element becomes the Nth element.
If N < 0,
the rotation is bubble down,
so that the Nth element becomes the top most element.    if (num_entries >= -1 && num_entries <= 1) {
        return;
    }
    if (num_entries < 0) {
        INTVAL i;
        Stack_Entry_t temp;
        INTVAL depth;
        num_entries = -num_entries;
        depth = num_entries - 1;
        if (stack_height(interp, stack) < (size_t)num_entries) {
            real_exception(interp, NULL, ERROR_STACK_SHALLOW, "Stack too shallow!");
        }
        /* XXX Dereferencing stack_entry here is a cavalcade of danger */
        temp = *stack_entry(interp, stack, depth);
        for (i = depth; i > 0; i--) {
            *stack_entry(interp, stack, i) =
                *stack_entry(interp, stack, i - 1);
        }
        *stack_entry(interp, stack, 0) = temp;
    }
    else {
        INTVAL i;
        Stack_Entry_t temp;
        INTVAL depth = num_entries - 1;
        if (stack_height(interp, stack) < (size_t)num_entries) {
            real_exception(interp, NULL, ERROR_STACK_SHALLOW, "Stack too shallow!");
        }
        /* XXX Dereferencing stack_entry here is a cavalcade of danger */
        temp = *stack_entry(interp, stack, 0);
        for (i = 0; i < depth; i++) {
            *stack_entry(interp, stack, i) =
                *stack_entry(interp, stack, i + 1);
        }
        *stack_entry(interp, stack, depth) = temp;
    }
}
void stack_pushNULL, points to a routine that'll be called when the entry is removed from the stack. This is handy for those cases where you need some sort of activity to take place when an entry is removed, such as when you push a lexical lock onto the call stack, or localize (or tempify, or whatever we're calling it) variable or something.    /* Remember the type */
    entry->entry_type = type;
    /* Remember the cleanup function */
    entry->cleanup = cleanup;
    /* Store our thing */
    switch (type) {
        case STACK_ENTRY_MARK:
            UVal_int(entry->entry) = *(INTVAL *)thing;
            break;
        case STACK_ENTRY_DESTINATION:
            UVal_ptr(entry->entry) = thing;
            break;
        case STACK_ENTRY_ACTION:
        case STACK_ENTRY_PMC:
            UVal_pmc(entry->entry) = (PMC *)thing;
            break;
        default:
            real_exception(interp, NULL, ERROR_BAD_STACK_TYPE,
                    "Invalid Stack_Entry_type!");
    }
}
void *stack_pop    /* Types of 0 mean we don't care */
    if (type && entry->entry_type != type) {
        real_exception(interp, NULL, ERROR_BAD_STACK_TYPE,
                           "Wrong type on top of stack!\n");
    }
    /* Cleanup routine? */
    if (entry->cleanup != STACK_CLEANUP_NULL)
        (*entry->cleanup) (interp, entry);
    /* Sometimes the caller cares what the value was */
    if (where) {
        /* Snag the value */
        switch (type) {
        case STACK_ENTRY_MARK:
            *(INTVAL *)where   = UVal_int(entry->entry);
            break;
        case STACK_ENTRY_DESTINATION:
            *(void **)where    = UVal_ptr(entry->entry);
            break;
        case STACK_ENTRY_ACTION:
        case STACK_ENTRY_PMC:
            *(PMC **)where     = UVal_pmc(entry->entry);
            break;
        default:
            real_exception(interp, NULL, ERROR_BAD_STACK_TYPE,
                               "Wrong type on top of stack!\n");
        }
    }
    /* recycle this chunk to the free list if it's otherwise unreferenced */
    if (cur_chunk->refcount <= 0) {
        Small_Object_Pool * const pool =
            get_bufferlike_pool(interp, cur_chunk->size);
        pool->dod_object(interp, pool, (PObj *)cur_chunk);
        pool->add_free_object(interp, pool, (PObj *)cur_chunk);
    }
    return where;
}
void *pop_destvoid *stack_peekStack_entry_type get_entry_typeentry.void Parrot_dump_dynamic_environmentPIO_eprintf). This is used only temporarily for debugging.
include/parrot/stacks.h, include/parrot/enums.h, and src/stack_common.c
|  |   |