void insert_looped_placeholders(Block* contents) { Value names; list_names_that_must_be_looped(contents, &names); for (ListIterator it(&names); it; ++it) { Term* inputPlaceholder = append_input_placeholder(contents); Value* name = it.value(); rename(inputPlaceholder, name); Value owningTermVal; owningTermVal.set_term(contents->owningTerm); Term* outsideTerm = find_name_at(&owningTermVal, name); Term* innerResult = find_local_name(contents, name); Term* outputPlaceholder = append_output_placeholder(contents, innerResult); rename(outputPlaceholder, name); set_inputs(inputPlaceholder, TermList(outsideTerm, outputPlaceholder)); for (BlockInputIterator it(contents); it; ++it) { Term* term = it.currentTerm(); if (it.currentInput() == outsideTerm && term != inputPlaceholder) set_input(term, it.currentInputIndex(), inputPlaceholder); } } }
void list_names_that_must_be_looped(Block* contents, Value* names) { // Find all names within 'contents' that must be looped. A name must be looped when // a term inside the loop binds a name that was already used outside the loop. Value namesMap; set_hashtable(&namesMap); for (BlockIteratorFlat it(contents); it; ++it) { Term* term = it.current(); if (has_empty_name(term)) continue; Value termVal; termVal.set_term(contents->owningTerm); Term* outsideName = find_name_at(&termVal, term_name(term)); // Don't look at names outside the major block. if (outsideName != NULL && !is_under_same_major_block(term, outsideName)) outsideName = NULL; if (outsideName != NULL) set_bool(hashtable_insert(&namesMap, term_name(term)), true); } hashtable_get_keys(&namesMap, names); list_sort(names, NULL, NULL); }
void add_implicit_placeholders(Term* forTerm) { Branch* contents = nested_contents(forTerm); std::string listName = forTerm->input(0)->name; Term* iterator = for_loop_get_iterator(contents); std::string iteratorName = iterator->name; std::vector<std::string> reboundNames; list_names_that_this_branch_rebinds(contents, reboundNames); int inputIndex = 1; for (size_t i=0; i < reboundNames.size(); i++) { std::string const& name = reboundNames[i]; if (name == listName) continue; if (name == iteratorName) continue; Term* original = find_name_at(forTerm, name.c_str()); // The name might not be found, for certain parser errors. if (original == NULL) continue; Term* result = contents->get(name); // Create input_placeholder Term* input = apply(contents, FUNCS.input, TermList(), name_from_string(name)); Type* type = find_common_type(original->type, result->type); change_declared_type(input, type); contents->move(input, inputIndex); set_input(forTerm, inputIndex, original); // Repoint terms to use our new input_placeholder for (BranchIterator it(contents); it.unfinished(); it.advance()) remap_pointers_quick(*it, original, input); // Create output_placeholder Term* term = apply(contents, FUNCS.output, TermList(result), name_from_string(name)); // Move output into the correct output slot contents->move(term, contents->length() - 1 - inputIndex); inputIndex++; } }
Term* if_block_add_output_for_name(Term* ifCall, const char* name) { // Fix the new output placeholders to have the correct name and input. Branch* mainBranch = nested_contents(ifCall); int outputCount = count_output_placeholders(mainBranch); Term* outputPlaceholder = if_block_append_output(ifCall); rename(outputPlaceholder, name); for (CaseIterator it(mainBranch); it.unfinished(); it.advance()) { Branch* caseContents = nested_contents(it.current()); Term* casePlaceholder = get_output_placeholder(caseContents, outputCount); ca_assert(casePlaceholder != NULL); ca_assert(casePlaceholder->name == ""); rename(casePlaceholder, name); set_input(casePlaceholder, 0, find_name_at(casePlaceholder, name)); respecialize_type(casePlaceholder); } return outputPlaceholder; }