Ejemplo n.º 1
0
static value_t List_push( PREFUNC, value_t listObj, value_t value )
{
	ARGCHECK_2( listObj, value );
	value_t head_chunk = listObj->slots[LIST_HEAD_CHUNK_SLOT];
	value_t cold_storage = listObj->slots[LIST_COLD_STORAGE_SLOT];
	value_t tail_chunk = listObj->slots[LIST_TAIL_CHUNK_SLOT];

	// If our head chunk has space remaining, push this value onto it. If the
	// chunk is full, we will push it onto the cold storage list and create a
	// new, one-element chunk for the new value, which becomes our head chunk.
	// This way the cold storage is a list of chunks, not a list of values.
	if (!chunk_can_grow( head_chunk )) {
		// Pushing a chunk onto cold storage is a potentially O(log n)
		// operation, as is popping a chunk. Therefore instead of pushing the
		// whole chunk, we will push only the last three elements. Our new
		// head chunk will include the new value and the previous head. This
		// way, an inexpensive pop always follows an expensive push, and vice
		// versa, which is how we get amortized O(1) performance.
		value_t pushable = chunk_pop( zone, head_chunk );
		cold_storage = METHOD_1( cold_storage, sym_push, pushable );
		head_chunk = chunk_alloc_1( zone, chunk_head( head_chunk ) );
	}
	// Push the new value onto our head chunk, which may or may not have been
	// freshly created for the purpose.
	head_chunk = chunk_push( zone, head_chunk, value );

	return alloc_list( zone, head_chunk, cold_storage, tail_chunk );
}
Ejemplo n.º 2
0
/** @brief Copy to file and save to chunk. */
static int
copy_save(void *arg_, const char *data, size_t len)
{
	s_copy_save *arg = arg_;

	if (arg->copy && file_write(arg->file, data, len))
		return -1;

	if (arg->save && chunk_push(arg->save, data, len))
		return -1;

	return 0;
}
Ejemplo n.º 3
0
static value_t List_concatenate(
		PREFUNC, value_t listObj, value_t otherList )
{
	ARGCHECK_2( listObj, otherList );
	// If the list to be concatenated is also a multi-item list, we will do an
	// efficient concatenation by taking advantage of our knowledge of its
	// internal structure. Otherwise, we will hope it is a sequence and append
	// each of its items.
	if (otherList->function == (function_t)List_function) {
		value_t ourHeadChunk = listObj->slots[LIST_HEAD_CHUNK_SLOT];
		value_t ourColdStorage = listObj->slots[LIST_COLD_STORAGE_SLOT];
		value_t ourTailChunk = listObj->slots[LIST_TAIL_CHUNK_SLOT];
		value_t otherHeadChunk = otherList->slots[LIST_HEAD_CHUNK_SLOT];
		value_t otherColdStorage = otherList->slots[LIST_COLD_STORAGE_SLOT];
		value_t otherTailChunk = otherList->slots[LIST_TAIL_CHUNK_SLOT];
		// We need to put these chunks into cold storage somehow. There are
		// enough possibilities that it would be tedious to do it all with if-
		// statements. Instead, we have this matrix, which will map each of the
		// sixteen possible combinations down to one of six actions. The
		// horizontal axis represents the size of the other list's head chunk;
		// the vertical axis represents the size of our list's tail chunk.
		int actions[4][4] = {
			{0, 1, 2, 2},
			{0, 4, 4, 2},
			{3, 4, 4, 5},
			{3, 3, 5, 5}};
		int x_size = chunk_item_count(otherHeadChunk);
		int y_size = chunk_item_count(ourTailChunk);
		switch(actions[y_size][x_size]) {
			case 0: {
				// Append other chunk's head to our chunk. Append our chunk to
				// our cold storage; let the other chunk drop.
				value_t item = chunk_head( otherHeadChunk );
				ourTailChunk = chunk_append( zone, ourTailChunk, item );
				ourColdStorage = 
					METHOD_1( ourColdStorage, sym_append, ourTailChunk );
			} break;
			case 1: {
				// Push our chunk's tail onto the other chunk. Push the other
				// chunk onto its cold storage, then let ours drop.
				value_t item = chunk_tail( zone, ourTailChunk );
				otherHeadChunk = chunk_push( zone, otherHeadChunk, item );
				otherColdStorage =
					METHOD_1( otherColdStorage, sym_push, otherHeadChunk );
			} break;
			case 2: {
				// Append other chunk's head to our chunk. Append our chunk to
				// our cold storage and push the other chunk onto its.
				value_t item = chunk_head( otherHeadChunk );
				otherHeadChunk = chunk_pop( zone, otherHeadChunk );
				otherColdStorage =
					METHOD_1( otherColdStorage, sym_push, otherHeadChunk );
				ourTailChunk = chunk_append( zone, ourTailChunk, item );
				ourColdStorage =
					METHOD_1( ourColdStorage, sym_append, ourTailChunk );
			} break;
			case 3: {
				// Push our chunk's tail onto the other chunk. Put each chunk
				// into its own cold storage.
				value_t item = chunk_tail( zone, ourTailChunk );
				ourTailChunk = chunk_chop( zone, ourTailChunk );
				ourColdStorage =
					METHOD_1( ourColdStorage, sym_append, ourTailChunk );
				otherHeadChunk = chunk_push( zone, otherHeadChunk, item );
				otherColdStorage = 
					METHOD_1( otherColdStorage, sym_push, otherHeadChunk );
			} break;
			case 4: {
				// Put each chunk into its own cold storage.
				ourColdStorage =
					METHOD_1( ourColdStorage, sym_append, ourTailChunk );
				otherColdStorage =
					METHOD_1( otherColdStorage, sym_push, otherHeadChunk );
			} break;
			case 5: {
				// Split one item off of each chunk to create a new middle
				// chunk. Put each original chunk onto its own list, then add
				// the middle chunk to our cold storage.
				value_t item = chunk_tail( zone, ourTailChunk );
				ourTailChunk = chunk_chop( zone, ourTailChunk );
				ourColdStorage =
					METHOD_1( ourColdStorage, sym_append, ourTailChunk );

				value_t midChunk = chunk_alloc_1( zone, item );
				item = chunk_head( otherHeadChunk );
				otherHeadChunk = chunk_pop( zone, otherHeadChunk );
				otherColdStorage =
					METHOD_1( otherColdStorage, sym_push, otherHeadChunk );

				midChunk = chunk_append( zone, midChunk, item );
				ourColdStorage =
					METHOD_1( ourColdStorage, sym_append, midChunk );
			} break;
		}
		// Having dealt with the active chunks, we now have a head chunk for
		// the whole list, a tail chunk for the whole list, and two cold
		// storage lists. We will recursively concatenate the cold storage
		// lists, then assemble our output list from these pieces.
		value_t combined_storage =
			METHOD_1( ourColdStorage, sym_concatenate, otherColdStorage );
		listObj = alloc_list(
				zone, ourHeadChunk, combined_storage, otherTailChunk );
	}
	else {
		value_t iter = METHOD_0( otherList, sym_iterate );
		if (IsAnException( iter )) return iter;
		while (BoolFromBoolean( zone, METHOD_0( iter, sym_is_valid ) )) {
			value_t val = METHOD_0( iter, sym_current );
			listObj = METHOD_1( listObj, sym_append, val );
			iter = METHOD_0( iter, sym_next );
		}
	}
	return listObj;
}
Ejemplo n.º 4
0
void forward_push_term( forward_t *f, uint32_t term ) {
	chunk_push( &f->chunk, term );
}