void UpwardIterator2::advanceWhileInvalid() { possibly_invalid: if (finished()) return; if (index < 0) { // Stop if we've finished the lastBlock. if (block == lastBlock) { block = NULL; return; } Block* previousBlock = block; block = get_parent_block(block); Term* parentTerm = parent_term(previousBlock); if (block == NULL || parentTerm == NULL) { block = NULL; return; } index = parentTerm->index - 1; goto possibly_invalid; } }
void get_relative_name_as_list(Term* term, Block* relativeTo, Value* nameOutput) { set_list(nameOutput, 0); // Walk upwards and build the name, stop when we reach relativeTo. // The output list will be reversed but we'll fix that. while (true) { set_value(list_append(nameOutput), unique_name(term)); if (term->owningBlock == relativeTo) { break; } term = parent_term(term); // If term is null, then it wasn't really a child of relativeTo if (term == NULL) { set_null(nameOutput); return; } } // Fix output list list_reverse(nameOutput); }
// Returns whether or not we succeeded bool get_relative_name_recursive(Block* block, Term* term, std::stringstream& output) { if (name_is_reachable_from(term, block)) { output << term->name(); return true; } Term* parentTerm = parent_term(term); if (parentTerm == NULL) return false; // Don't include the names of hidden or builtin blocks. if (is_hidden(parentTerm)) { output << term->name(); return true; } if (parentTerm->nestedContents != NULL && block_get_bool_prop(parentTerm->nestedContents, s_Builtins, false)) { output << term->name(); return true; } bool success = get_relative_name_recursive(block, parentTerm, output); if (!success) return false; output << ":" << term->name(); return true; }
Term* parent_term(Term* term, int levels) { for (int i=0; i < levels; i++) { term = parent_term(term); if (term == NULL) return NULL; } return term; }
bool term_is_child_of_block(Term* term, Block* block) { while (term != NULL) { if (term->owningBlock == block) return true; term = parent_term(term); } return false; }
Term* find_parent_term_in_block(Term* term, Block* block) { while (true) { if (term == NULL) return NULL; if (term->owningBlock == block) return term; term = parent_term(term); } }
Term* find_enclosing_for_loop(Term* location) { while (location != NULL && location->function != FUNCS.for_func) location = parent_term(location); return location; }