ListData* list_remove_index(ListData* original, int index) { ca_assert(index < original->count); ListData* result = list_touch(original); for (int i=index; i < result->count - 1; i++) swap(&result->items[i], &result->items[i+1]); set_null(&result->items[result->count - 1]); result->count--; return result; }
void compound_type_append_field(Type* type, Type* fieldType, const char* fieldName) { ca_assert(list_get_parameter_type(&type->parameter) == name_StructType); list_touch(&type->parameter); caValue* types = list_get(&type->parameter, 0); caValue* names = list_get(&type->parameter, 1); set_type(list_append(types), fieldType); set_string(list_append(names), fieldName); }
void list_remove_and_replace_with_last_element(ListData** data, int index) { *data = list_touch(*data); ca_assert(index < (*data)->count); set_null(&(*data)->items[index]); int lastElement = (*data)->count - 1; if (index < lastElement) swap(&(*data)->items[index], &(*data)->items[lastElement]); (*data)->count--; }
caValue* list_append(ListData** dataPtr) { if (*dataPtr == NULL) { *dataPtr = allocate_empty_list(1); } else { *dataPtr = list_touch(*dataPtr); if ((*dataPtr)->count == (*dataPtr)->capacity) *dataPtr = list_double_capacity(*dataPtr); } ListData* data = *dataPtr; data->count++; return &data->items[data->count - 1]; }
void list_remove_nulls(ListData** dataPtr) { if (*dataPtr == NULL) return; *dataPtr = list_touch(*dataPtr); ListData* data = *dataPtr; int numRemoved = 0; for (int i=0; i < data->count; i++) { if (is_null(&data->items[i])) numRemoved++; else swap(&data->items[i - numRemoved], &data->items[i]); } *dataPtr = list_resize(*dataPtr, data->count - numRemoved); }
ListData* list_resize(ListData* original, int newLength) { // Check if 'original' is an empty list. if (original == NULL) { // If newLength is 0 then no change. if (newLength == 0) return NULL; // Create a new empty list. ListData* result = allocate_empty_list(newLength); result->count = newLength; return result; } // Special case: if newLength is 0 then return an empty list. if (newLength == 0) { list_decref(original); return NULL; } // Check if the new length is the same as the old length. if (original->count == newLength) return original; // Increase capacity if necessary. if (newLength > original->capacity) { ListData* result = list_increase_capacity(original, newLength); result->count = newLength; return result; } // At this point the capacity is good, we need to modify list->count, and // discard some rightmost elements. ListData* result = list_touch(original); // Set rightmost elements to null, if we are shrinking. for (int i=newLength; i < result->count; i++) set_null(&result->items[i]); result->count = newLength; return result; }
void tv_cast(CastResult* result, caValue* value, Type* type, bool checkOnly) { if (!is_list(value)) { result->success = false; return; } int sourceLength = list_length(value); // If the requested type doesn't have a specific size restriction, then // the input data is fine as-is. if (!list_type_has_specific_size(&type->parameter)) { if (!checkOnly) value->value_type = type; return; } List& destTypes = *List::checkCast(list_get_type_list_from_type(type)); // Check for correct number of elements. if (sourceLength != destTypes.length()) { result->success = false; return; } if (!checkOnly) { INCREMENT_STAT(Touch_ListCast); list_touch(value); value->value_type = type; } for (int i=0; i < sourceLength; i++) { caValue* sourceElement = list_get(value, i); Type* expectedType = as_type(destTypes[i]); INCREMENT_STAT(Cast_ListCastElement); cast(result, sourceElement, expectedType, checkOnly); if (!result->success) return; } }
void for_loop_finish_iteration(Stack* stack, bool enableLoopOutput) { INCREMENT_STAT(LoopFinishIteration); Frame* frame = top_frame(stack); Branch* contents = frame->branch; // Find list length caValue* listInput = get_frame_register(frame, 0); // Increment the loop index caValue* index = get_top_register(stack, for_loop_find_index(contents)); set_int(index, as_int(index) + 1); // Preserve list output if (enableLoopOutput && frame->exitType != name_Discard) { caValue* outputIndex = get_frame_register(frame, for_loop_find_output_index(contents)); Term* outputPlaceholder = get_output_placeholder(contents, 0); caValue* outputList = get_frame_register(frame, outputPlaceholder); caValue* outputValue = find_stack_value_for_term(stack, outputPlaceholder->input(0), 0); if (!is_list(outputList)) set_list(outputList); list_touch(outputList); copy(outputValue, list_get(outputList, as_int(outputIndex))); INCREMENT_STAT(LoopWriteOutput); // Advance output index set_int(outputIndex, as_int(outputIndex) + 1); } // Check if we are finished if (as_int(index) >= list_length(listInput) || frame->exitType == name_Break || frame->exitType == name_Return) { // Possibly truncate output list, in case any elements were discarded. if (enableLoopOutput) { caValue* outputIndex = get_frame_register(frame, for_loop_find_output_index(contents)); Term* outputPlaceholder = get_output_placeholder(contents, 0); caValue* outputList = get_frame_register(frame, outputPlaceholder); list_resize(outputList, as_int(outputIndex)); } else { Term* outputPlaceholder = get_output_placeholder(contents, 0); caValue* outputList = get_frame_register(frame, outputPlaceholder); set_list(outputList, 0); } finish_frame(stack); return; } // If we're not finished yet, copy rebound outputs back to inputs. for (int i=1;; i++) { Term* input = get_input_placeholder(contents, i); if (input == NULL) break; Term* output = get_output_placeholder(contents, i); copy(get_frame_register(frame, output), get_frame_register(frame, input)); INCREMENT_STAT(Copy_LoopCopyRebound); } // Return to start of loop body frame->pc = 0; frame->nextPc = 0; frame->exitType = name_None; }
void List::set(int index, caValue* value) { list_touch(this); copy(value, list_get(this, index)); }
void tv_touch(caValue* value) { ca_assert(is_list(value)); ListData* data = (ListData*) get_pointer(value); set_pointer(value, list_touch(data)); }
void tv_set_index(caValue* value, int index, caValue* element) { ca_assert(is_list(value)); list_touch(value); copy(element, list_get(value, index)); }
void list_touch(caValue* list) { list->value_data.ptr = (ListData*) list_touch((ListData*) list->value_data.ptr); }