Block* find_block_that_exit_point_will_reach(Term* term) { ca_assert(is_exit_point(term)); Block* block = term->owningBlock; // 'return' exits to nearest major block. if (term->function == FUNCS.return_func) { while (is_minor_block(block)) { Block* parent = get_parent_block(block); if (parent == NULL) return block; block = parent; } return block; } // 'case_condition_bool' exits the current if-block. if (term->function == FUNCS.case_condition_bool) return get_parent_block(term->owningBlock); // Otherwise, exit to nearest for-loop. while (!is_for_loop(block) && !is_while_loop(block)) { Block* parent = get_parent_block(block); if (parent == NULL) return block; block = parent; } return block; }
void list_remove_index(caValue* list, int index) { ca_assert(list->value_type->storageType == name_StorageTypeList); ListData* data = (ListData*) list->value_data.ptr; list_remove_index(data, index); list->value_data.ptr = data; }
void migrate_block(Block* target, Migration* migration) { ca_assert(target != migration->oldBlock); if (target == migration->newBlock) return; // Store a cache of lookups that we've made in this call. TermMap cache; for (BlockIterator it(target); it; ++it) { Term* term = *it; // Iterate through each "dependency", which includes the function & inputs. for (int i=0; i < term->numDependencies(); i++) { Term* ref = term->dependency(i); Term* newRef = NULL; if (cache.contains(ref)) { newRef = cache[ref]; } else { // Lookup and save result in cache newRef = migrate_term_pointer(ref, migration); cache[ref] = newRef; } // Possibly rebind if (newRef != ref) term->setDependency(i, newRef); } } }
void handle_release(caValue* value) { HandleData* container = as_handle(value); ca_assert(container != NULL); container->refcount--; // Release data, if this is the last reference. if (container->refcount <= 0) { // Find the type's release function (if any), and call it. Term* releaseMethod = find_method(NULL, value->value_type, "release"); if (releaseMethod != NULL) { Stack stack; push_frame(&stack, function_contents(releaseMethod)); caValue* inputSlot = get_input(&stack, 0); // Don't copy this value, otherwise we'll get in trouble when the copy // needs to be released. swap(value, inputSlot); run_interpreter(&stack); swap(value, inputSlot); } free(container); } }
void log_finish() { ca_assert(g_logInProgress); fprintf(g_logFile, ")\n"); g_logInProgress = false; g_logArgCount = 0; }
void modify_branch_so_that_state_access_is_indexed(Branch* branch, int index) { Term* stateInput = find_state_input(branch); if (stateInput == NULL) return; // If the state output is connected directly to state input, then do nothing. Term* stateOutput = find_state_output(branch); if (stateOutput->input(0) == stateInput) return; Term* unpackList = apply(branch, FUNCS.unpack_state_from_list, TermList(stateInput)); unpackList->setIntProp("index", index); move_after_inputs(unpackList); for (int i=0; i < stateInput->users.length(); i++) { Term* term = stateInput->users[i]; if (term == unpackList) continue; remap_pointers_quick(term, stateInput, unpackList); } Term* stateResult = stateOutput->input(0); ca_assert(stateResult != NULL); Term* packList = apply(branch, FUNCS.pack_state_to_list, TermList(stateInput, stateResult)); packList->setIntProp("index", index); packList->setBoolProp("final", true); set_input(stateOutput, 0, packList); move_after(packList, stateResult); }
// For the given field name static Term* find_output_term_for_state_field(Branch* branch, const char* fieldName, int position) { Term* result = find_from_unique_name(branch, fieldName); // For declared state, the result is the last term with the given name if (result->function == FUNCS.declared_state) { return find_local_name(branch, result->name.c_str(), position); } ca_assert(result != NULL); // This term might be the actual state result, or the state result might be // found in an extra output. Look around and see if this term has a stateful // extra output. for (int outputIndex=0;; outputIndex++) { Term* extraOutput = get_extra_output(result, outputIndex); if (extraOutput == NULL) break; if (is_state_output(extraOutput)) return extraOutput; } return result; }
void list_resize(caValue* list, int size) { ca_assert(list->value_type->storageType == name_StorageTypeList); ListData* data = (ListData*) list->value_data.ptr; data = list_resize(data, size); list->value_data.ptr = data; }
void file_watch_trigger_actions(World* world, FileWatch* watch) { // Walk through each action and execute it. for (int i = 0; i < list_length(&watch->onChangeActions); i++) { caValue* action = list_get(&watch->onChangeActions, i); Symbol label = first_symbol(action); ca_assert(label != sym_None); switch (label) { case sym_NativePatch: { caValue* moduleName = list_get(action, 1); NativePatch* nativeModule = add_native_patch(world, as_cstring(moduleName)); native_patch_load_from_file(nativeModule, as_cstring(&watch->filename)); native_patch_finish_change(nativeModule); break; } case sym_PatchBlock: { // Reload this code block. caValue* moduleName = list_get(action, 1); load_module_file(world, as_cstring(moduleName), as_cstring(&watch->filename)); break; } default: internal_error("unrecognized file watch action"); } } }
void if_block_create_input_placeholders_for_outer_pointers(Term* ifCall) { Branch* contents = nested_contents(ifCall); TermList outerTerms; // Find outer pointers across each case for (CaseIterator it(contents); it.unfinished(); it.advance()) { list_outer_pointers(nested_contents(it.current()), &outerTerms); } ca_assert(ifCall->numInputs() == 0); // Create input placeholders and add inputs for all outer pointers for (int i=0; i < outerTerms.length(); i++) { Term* outer = outerTerms[i]; set_input(ifCall, i, outer); Term* placeholder = append_input_placeholder(nested_contents(ifCall)); rename(placeholder, outer->name); // Go through each case and repoint to this new placeholder for (CaseIterator it(contents); it.unfinished(); it.advance()) { remap_pointers_quick(nested_contents(it.current()), outer, placeholder); } } }
/** * ca_context_cache_full: * @c: The context to use for uploading. * @p: The property list for this event sound. * * Upload the specified sample into the server and attach the * specified properties to it. Similar to ca_context_cache() but takes * a ca_proplist instead of a variable number of arguments. * * If the backend doesn't support caching sound samples this function * will return CA_ERROR_NOTSUPPORTED. * * Returns: 0 on success, negative error code on error. */ int ca_context_cache_full(ca_context *c, ca_proplist *p) { int ret; ca_return_val_if_fail(!ca_detect_fork(), CA_ERROR_FORKED); ca_return_val_if_fail(c, CA_ERROR_INVALID); ca_return_val_if_fail(p, CA_ERROR_INVALID); ca_mutex_lock(c->mutex); ca_return_val_if_fail_unlock(ca_proplist_contains(p, CA_PROP_EVENT_ID) || ca_proplist_contains(c->props, CA_PROP_EVENT_ID), CA_ERROR_INVALID, c->mutex); if ((ret = context_open_unlocked(c)) < 0) goto finish; ca_assert(c->opened); ret = driver_cache(c, p); finish: ca_mutex_unlock(c->mutex); return ret; }
const char* as_cstring(caValue* value) { ca_assert(value->value_type->storageType == sym_StorageTypeString); StringData* data = (StringData*) value->value_data.ptr; if (data == NULL) return ""; return data->str; }
caValue* list_insert(caValue* list, int index) { ca_assert(list->value_type->storageType == name_StorageTypeList); ListData* data = (ListData*) list->value_data.ptr; caValue* result = list_insert(&data, index); list->value_data.ptr = data; return result; }
unsigned ca_vorbis_get_rate(ca_vorbis *v) { const vorbis_info *vi; ca_assert(v); ca_assert_se(vi = ov_info(&v->ovf, -1)); return (unsigned) vi->rate; }
int test_handle_find_free_slot() { for (int i=0; i < g_testHandleSlots; i++) if (!g_testHandleAllocated[i]) return i; ca_assert(false); return 0; }
void string_append(caValue* left, int value) { ca_assert(is_string(left)); char buf[64]; sprintf(buf, "%d", value); string_append(left, buf); }
std::string tv_to_string(caValue* value) { ca_assert(is_list(value)); if (is_compound_type(value->value_type)) return compound_type_to_string(value); return list_to_string((ListData*) get_pointer(value)); }
void tv_release(caValue* value) { ca_assert(is_list(value)); ListData* data = (ListData*) get_pointer(value); if (data == NULL) return; list_decref(data); }
caValue* list_get_name_list_from_type(Type* type) { ca_assert(is_list_based_type(type)); caValue* parameter = &type->parameter; switch (list_get_parameter_type(parameter)) { case name_StructType: return list_get(parameter, 1); case name_AnonStructType: case name_Untyped: case name_UniformListType: case name_Invalid: return NULL; } ca_assert(false); return NULL; }
void decref(StringData* data) { ca_assert(data->refCount > 0); data->refCount--; if (data->refCount == 0) { free(data); } }
unsigned ca_vorbis_get_nchannels(ca_vorbis *v) { const vorbis_info *vi; ca_assert(v); ca_assert_se(vi = ov_info(&v->ovf, -1)); return (unsigned) vi->channels; }
caValue* list_append(caValue* list) { ca_assert(list->value_type->storageType == name_StorageTypeList); ListData* data = (ListData*) list->value_data.ptr; caValue* result = list_append(&data); list->value_data.ptr = data; return result; }
Term* Block::appendNew() { Term* term = alloc_term(this); ca_assert(term != NULL); _terms.append(term); term->index = _terms.length()-1; return term; }
const ca_channel_position_t* ca_sound_file_get_channel_map(ca_sound_file *f) { ca_assert(f); if (f->wav) return ca_wav_get_channel_map(f->wav); else return ca_vorbis_get_channel_map(f->vorbis); }
std::string TokenStream::nextStr(int lookahead) const { int startPos = next(lookahead).start; int length = next(lookahead).length(); ca_assert(length > 0); return std::string(_sourceText.c_str() + startPos, length); }
void log_arg(const char* key, const char* val) { ca_assert(g_logInProgress); if (g_logArgCount > 0) fprintf(g_logFile, ", "); fprintf(g_logFile, "%s = %s", key, val); g_logArgCount++; }
void Block::insert(int index, Term* term) { ca_assert(index >= 0); ca_assert(index <= _terms.length()); _terms.append(NULL); for (int i=_terms.length()-1; i > index; i--) { _terms.setAt(i, _terms[i-1]); _terms[i]->index = i; } _terms.setAt(index, term); if (term != NULL) { ca_assert(term->owningBlock == NULL); term->owningBlock = this; term->index = index; } }
void Block::append(Term* term) { _terms.append(term); if (term != NULL) { ca_assert(term->owningBlock == NULL); term->owningBlock = this; term->index = _terms.length()-1; } }
size_t ca_sound_file_frame_size(ca_sound_file *f) { unsigned c; ca_assert(f); c = ca_sound_file_get_nchannels(f); return c * (ca_sound_file_get_sample_type(f) == CA_SAMPLE_U8 ? 1U : 2U); }
void list_decref(ListData* data) { assert_valid_list(data); ca_assert(data->refCount > 0); data->refCount--; if (data->refCount == 0) free_list(data); }