void finish_if_block(Term* ifBlock) { Branch* contents = nested_contents(ifBlock); // Make sure there is a primary output if (get_output_placeholder(contents, 0) == NULL) if_block_prepend_primary_output(ifBlock); if_block_normalize_state_inputs(ifBlock); int caseIndex = 0; for (CaseIterator it(contents); it.unfinished(); it.advance()) { Term* term = it.current(); if_block_turn_outer_name_rebinds_into_outputs(ifBlock, nested_contents(term)); if_block_fix_outer_pointers(ifBlock, nested_contents(term)); modify_branch_so_that_state_access_is_indexed(nested_contents(term), caseIndex); caseIndex++; } if_block_turn_common_rebinds_into_outputs(ifBlock); if_block_update_output_placeholder_types_from_cases(ifBlock); check_to_insert_implicit_inputs(ifBlock); update_extra_outputs(ifBlock); }
Term* if_block_append_case(Term* ifBlock, Term* input) { Branch* contents = nested_contents(ifBlock); int insertPos = 0; for (int i=0; i < contents->length(); i++) { Term* term = contents->get(i); if (term->function == FUNCS.input) insertPos = term->index + 1; // Insert position is right after the last non-default case. if (term->function == FUNCS.case_func && term->input(0) != NULL) insertPos = term->index + 1; } Term* newCase = apply(contents, FUNCS.case_func, TermList(input)); contents->move(newCase, insertPos); // Add existing input placeholders to this case for (int i=0;; i++) { Term* placeholder = get_input_placeholder(contents, i); if (placeholder == NULL) break; Term* localPlaceholder = append_input_placeholder(nested_contents(newCase)); change_declared_type(localPlaceholder, placeholder->type); } return newCase; }
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); } } }
Branch* load_module(const char* module_name, Term* loadCall) { Branch* existing = find_loaded_module(module_name); if (existing != NULL) return existing; Value filename; bool found = find_module_file(module_name, &filename); if (!found) return NULL; Term* import = load_module_from_file(module_name, as_cstring(&filename))->owningTerm; // If a loadCall is provided, possibly move the new import to be before the loadCall. if (loadCall != NULL) { Term* callersModule = find_parent_term_in_branch(loadCall, import->owningBranch); if (callersModule != NULL && (import->index > callersModule->index)) move_before(import, callersModule); } // If the module has static errors, print them now. print_static_errors_formatted(nested_contents(import)); return nested_contents(import); }
int run_repl() { Stack context; Branch branch; bool displayRaw = false; push_frame(&context, &branch); while (true) { std::cout << "> "; std::string input; if (!std::getline(std::cin, input)) break; if (input == "exit" || input == "/exit") break; if (input == "") continue; if (input == "/raw") { displayRaw = !displayRaw; if (displayRaw) std::cout << "Displaying raw output" << std::endl; else std::cout << "Not displaying raw output" << std::endl; continue; } if (input == "/clear") { clear_branch(&branch); std::cout << "Cleared working area" << std::endl; continue; } if (input == "/dump") { dump(&branch); continue; } if (input == "/help") { std::cout << "Special commands: /raw, /help, /clear, /dump, /exit" << std::endl; continue; } int previousHead = branch.length(); repl_evaluate_line(&context, input, std::cout); if (displayRaw) { for (int i=previousHead; i < branch.length(); i++) { std::cout << get_term_to_string_extended(branch[i]) << std::endl; if (nested_contents(branch[i])->length() > 0) print_branch(std::cout, nested_contents(branch[i])); } } } return 0; }
void if_block_finish_appended_case(Term* ifBlock, Term* caseTerm) { if_block_fix_outer_pointers(ifBlock, nested_contents(caseTerm)); // Add an output placeholder apply(nested_contents(caseTerm), FUNCS.output, TermList(find_last_non_comment_expression(nested_contents(caseTerm)))); //std::cout << "finished appended case.." << std::endl; }
void bug_with_is_major_block() { Block block; Term* f = block.compile("def f() {}"); test_assert(is_major_block(nested_contents(f))); // There was a bug where, if the function was patched with a native handler, it // would no longer be considered a major block. install_function(f, my_native_patch); test_assert(is_major_block(nested_contents(f))); }
Term* if_block_append_output(Term* ifBlock) { Branch* contents = nested_contents(ifBlock); Term* placeholder = append_output_placeholder(contents, NULL); // Add a corresponding output placeholder to each case for (CaseIterator it(contents); it.unfinished(); it.advance()) { Branch* caseContents = nested_contents(it.current()); /*Term* casePlaceholder =*/ append_output_placeholder(caseContents, NULL); } return placeholder; }
void BlockIterator2::advance() { // Possibly iterate through the contents of this block. if (has_nested_contents(_current) && nested_contents(_current)->length() > 0) { _current = nested_contents(_current)->get(0); return; } // Advance to next index. Block* block = _current->owningBlock; int index = _current->index + 1; // Possibly loop as we pop out of finished blocks. possibly_invalid: if (index >= block->length() || block == NULL) { // Finished this block. if (block == _topBlock || block == NULL) { // Finished the iteration. _current = NULL; _topBlock = NULL; return; } // Advance to the next term in the parent block. Term* parentTerm = block->owningTerm; if (parentTerm == NULL) { // No block parent. It's weird that we hit this case before we reached // the topBlock, but anyway, finish the iteration. _current = NULL; _topBlock = NULL; return; } block = parentTerm->owningBlock; index = parentTerm->index + 1; goto possibly_invalid; } // Skip over NULL terms. if (block->get(index) == NULL) { index++; goto possibly_invalid; } // Index is valid. Save the position as a Term*. _current = block->get(index); }
void finish_for_loop(Term* forTerm) { Branch* contents = nested_contents(forTerm); // Add a 'loop_output' term that will collect each iteration's output. Term* loopOutput = apply(contents, FUNCS.loop_output, TermList(loop_get_primary_result(contents))); // Add a primary output apply(contents, FUNCS.output, TermList(loopOutput)); // pack_any_open_state_vars(contents); for_loop_fix_state_input(contents); check_to_add_state_output_placeholder(contents); add_implicit_placeholders(forTerm); repoint_terms_to_use_input_placeholders(contents); check_to_insert_implicit_inputs(forTerm); update_extra_outputs(forTerm); loop_update_exit_points(contents); set_branch_in_progress(contents, false); }
Term* start_building_for_loop(Term* forTerm, const char* iteratorName, Type* iteratorType) { Branch* contents = nested_contents(forTerm); // Add input placeholder for the list input Term* listInput = apply(contents, FUNCS.input, TermList()); // Add loop_index() Term* index = apply(contents, FUNCS.loop_index, TermList(listInput)); hide_from_source(index); // Add get_index to fetch the list's current element. Term* iterator = apply(contents, FUNCS.get_index, TermList(listInput, index), name_from_string(iteratorName)); if (iteratorType == NULL) iteratorType = infer_type_of_get_index(forTerm->input(0)); change_declared_type(iterator, iteratorType); hide_from_source(iterator); // Add the zero branch create_branch_unevaluated(contents, "#zero"); // Add an loop output index Term* loopOutputIndex = apply(contents, FUNCS.loop_output_index, TermList()); return iterator; }
void patch_branch_recr(Dll* dll, Branch* branch, std::string namespacePrefix) { for (int i=0; i < branch->length(); i++) { Term* term = branch->get(i); if (is_namespace(term)) { patch_branch_recr(dll, nested_contents(term), namespacePrefix + term->name + "__"); } else if (is_function(term)) { std::string name = term->name; // Replace '.' with '_' for (size_t i=0; i < name.length(); i++) if (name[i] == '.') name[i] = '_'; std::string searchName = namespacePrefix + name; void* newEvaluateFunc = find_func_in_dll(dll, searchName.c_str()); // Patch in this function and record the affected term if (newEvaluateFunc != NULL) { function_set_evaluate_func(term, (EvaluateFunc) newEvaluateFunc); dll->affectedTerms.append(term); dll->loadedFunctions.insert(newEvaluateFunc); } } } }
void duplicate_block_nested(TermMap& newTermMap, Block* source, Block* dest) { // Duplicate every term for (int index=0; index < source->length(); index++) { Term* source_term = source->get(index); Term* dest_term = create_duplicate(dest, source_term, &source_term->nameValue); newTermMap[source_term] = dest_term; // duplicate nested contents clear_block(nested_contents(dest_term)); duplicate_block_nested(newTermMap, nested_contents(source_term), nested_contents(dest_term)); } }
Block* load_script_term(Block* block, const char* filename) { ca_assert(block != NULL); Term* filenameTerm = create_string(block, filename); Term* includeFunc = apply(block, FUNCS.load_script, TermList(filenameTerm)); return nested_contents(includeFunc); }
void switch_formatSource(caValue* source, Term* term) { format_name_binding(source, term); append_phrase(source, "switch ", term, name_Keyword); format_source_for_input(source, term, 0); format_branch_source(source, nested_contents(term), term); }
void finish_for_loop(Term* forTerm) { Branch* contents = nested_contents(forTerm); // Need to finish here to prevent error branch_finish_changes(contents); // Add a a primary output Term* primaryOutput = apply(contents, FUNCS.output, TermList(loop_get_primary_result(contents))); primaryOutput->setBoolProp("accumulatingOutput", true); respecialize_type(primaryOutput); // pack_any_open_state_vars(contents); for_loop_fix_state_input(contents); check_to_add_state_output_placeholder(contents); add_implicit_placeholders(forTerm); repoint_terms_to_use_input_placeholders(contents); check_to_insert_implicit_inputs(forTerm); update_extra_outputs(forTerm); branch_finish_changes(contents); }
void formatSource(StyledSource* source, Term* term) { format_heading(source, term); format_branch_source(source, nested_contents(term), term); append_phrase(source, term->stringPropOptional("syntax:whitespaceBeforeEnd", ""), term, TK_WHITESPACE); }
Branch* find_enclosing_for_loop_contents(Term* term) { Term* loop = find_enclosing_for_loop(term); if (loop == NULL) return NULL; return nested_contents(loop); }
Block* find_function_local(Block* block, const char* name) { caTerm* term = find_name(block, name, s_LookupFunction); if (term == NULL) return NULL; return nested_contents(term); }
void section_block_formatSource(caValue* source, Term* term) { format_name_binding(source, term); append_phrase(source, "section", term, sym_None); append_phrase(source, " ", term, sym_Whitespace); format_block_source(source, nested_contents(term), term); }
bool if_block_is_name_bound_in_every_case(Branch* contents, const char* name) { for (CaseIterator it(contents); it.unfinished(); it.advance()) { if (!nested_contents(it.current())->contains(name)) return false; } return true; }
const char* for_loop_get_iterator_name(Term* forTerm) { Term* iterator = for_loop_get_iterator(nested_contents(forTerm)); if (iterator == NULL) return ""; return iterator->name.c_str(); }
const char* for_loop_get_iterator_name(Term* forTerm) { Term* iterator = loop_find_iterator_value(nested_contents(forTerm)); if (iterator == NULL) return ""; return iterator->name(); }
void format_source(caValue* source, Term* term) { append_phrase(source, "namespace ", term, sym_Keyword); append_phrase(source, term->name, term, sym_TermName); format_block_source(source, nested_contents(term), term); append_phrase(source, term->stringProp("syntax:preEndWs", ""), term, tok_Whitespace); }
Block* term_get_dispatch_block(Term* term) { if (uses_dynamic_dispatch(term)) return NULL; if (term->function == FUNCS.if_block || term->function == FUNCS.switch_func || term->function == FUNCS.for_func || term->function == FUNCS.while_loop || term->function == FUNCS.include_func) return nested_contents(term); if (term->function == NULL) return NULL; return nested_contents(term->function); }
Branch* find_loaded_module(const char* name) { for (BranchIteratorFlat it(kernel()); it.unfinished(); it.advance()) { Term* term = it.current(); if (term->function == FUNCS.imported_file && term->name == name) return nested_contents(term); } return NULL; }
Term* if_block_prepend_primary_output(Term* ifBlock) { Branch* contents = nested_contents(ifBlock); Term* placeholder = prepend_output_placeholder(contents, NULL); for (CaseIterator it(contents); it.unfinished(); it.advance()) { Branch* caseContents = nested_contents(it.current()); Term* result = find_last_non_comment_expression(caseContents); // If the last term already has a name then don't make it the default output. if (result != NULL && result->name != "") result = NULL; prepend_output_placeholder(nested_contents(it.current()), result); } return placeholder; }
void if_block_normalize_state_inputs(Term* ifBlock) { Branch* contents = nested_contents(ifBlock); // Check if any branches have a state input bool anyState = false; for (CaseIterator it(contents); it.unfinished(); it.advance()) { if (has_state_input(nested_contents(it.current()))) anyState = true; } if (!anyState) return; append_state_placeholders_if_needed(contents); for (CaseIterator it(contents); it.unfinished(); it.advance()) append_state_placeholders_if_needed(nested_contents(it.current())); }
int if_block_count_cases(Term* term) { Branch* contents = nested_contents(term); int result = 0; for (int i=0; i < contents->length(); i++) if (contents->get(i) != NULL && contents->get(i)->function == FUNCS.case_func) result++; return result; }
void finish_while_loop(Term* whileTerm) { Branch* branch = nested_contents(whileTerm); // Append a call to unbounded_loop_finish() Term* term = apply(branch, FUNCS.unbounded_loop_finish, TermList()); move_before_outputs(term); }