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 trace_accessor_chain(Term* accessor, TermList* chainResult) { Term* bottomAccessor = accessor; chainResult->resize(0); while (true) { chainResult->append(accessor); // Stop when we find a named term. if (!has_empty_name(accessor)) break; if (accessor->function == FUNCS.get_index || accessor->function == FUNCS.get_field || is_copying_call(accessor) || accessor->function == FUNCS.dynamic_method || is_subroutine(accessor->function)) { // Continue the trace upward. accessor = accessor->input(0); continue; } // Accessor search can't continue past this term. break; } chainResult->reverse(); }
void Term__name(VM* vm) { Term* t = as_term_ref(vm->input(0)); if (t == NULL) return vm->throw_str("NULL term"); if (has_empty_name(t)) set_string(vm->output(), ""); else copy(term_name(t), vm->output()); }
void Block::bindName(Term* term, Value* name) { if (!has_empty_name(term) && !equals(&term->nameValue, name)) { internal_error(std::string("term already has a name: ") + term->nameStr()); } if (!is_null(name)) names.bind(term, as_cstring(name)); copy(name, &term->nameValue); update_unique_name(term); }
bool is_considered_config(Term* term) { if (term == NULL) return false; if (has_empty_name(term)) return false; if (!is_value(term)) return false; if (is_declared_state(term)) return false; if (is_hidden(term)) return false; if (is_function(term)) return false; if (is_type(term)) return false; return true; }
Term* rebind_possible_accessor(Branch* branch, Term* accessor, Term* result) { // Check if this isn't a recognized accessor. if (!has_empty_name(accessor)) { // Just create a named copy of 'result'. return apply(branch, FUNCS.copy, TermList(result), accessor->nameSymbol); } TermList accessorChain; trace_accessor_chain(accessor, &accessorChain); Term* head = accessorChain[0]; // Create the selector Term* selector = write_selector_for_accessor_chain(branch, &accessorChain); Term* set = apply(branch, FUNCS.set_with_selector, TermList(head, selector, result), head->nameSymbol); change_declared_type(set, declared_type(head)); return set; }
void Block::removeNameBinding(Term* term) { if (!has_empty_name(term) && names[term->name()] == term) names.remove(term->name()); }