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); }
void block_update_pack_state_calls(Block* block) { if (block->stateType == NULL) { // No state type, make sure there's no pack_state call. // TODO: Handle this case properly (should search and destroy an existing pack_state call) return; } int stateOutputIndex = block->length() - 1 - find_state_output(block)->index; for (int i=0; i < block->length(); i++) { Term* term = block->get(i); if (term == NULL) continue; if (term->function == FUNCS.pack_state) { // Update the inputs for this pack_state call TermList inputs; list_inputs_to_pack_state(block, i, &inputs); set_inputs(term, inputs); } else if (should_have_preceeding_pack_state(term)) { // Check if we need to insert a pack_state call Term* existing = term->input(stateOutputIndex); if (existing == NULL || existing->function != FUNCS.pack_state) { TermList inputs; list_inputs_to_pack_state(block, i, &inputs); if (inputs.length() != 0) { Term* pack_state = apply(block, FUNCS.pack_state, inputs); move_before(pack_state, term); // Only set as an input for a non-minor block. if (term->nestedContents == NULL || !is_minor_block(term->nestedContents)) { set_input(term, stateOutputIndex, pack_state); set_input_hidden(term, stateOutputIndex, true); set_input_implicit(term, stateOutputIndex, true); } // Advance i to compensate for the term just added i++; } } } } }
void branch_update_existing_pack_state_calls(Branch* branch) { if (branch->stateType == NULL) { // No state type, make sure there's no pack_state call. // TODO: Handle this case properly (should search and destroy an existing pack_state call) return; } int stateOutputIndex = branch->length() - 1 - find_state_output(branch)->index; for (int i=0; i < branch->length(); i++) { Term* term = branch->get(i); if (term == NULL) continue; if (term->function == FUNCS.pack_state) { // Update the inputs for this pack_state call TermList inputs; get_list_of_state_outputs(branch, i, &inputs); set_inputs(term, inputs); } if (term->function == FUNCS.exit_point) { // Check if we need to insert a pack_state call Term* existing = term->input(stateOutputIndex); if (existing == NULL || existing->function != FUNCS.pack_state) { TermList inputs; get_list_of_state_outputs(branch, i, &inputs); if (inputs.length() != 0) { Term* pack_state = apply(branch, FUNCS.pack_state, inputs); move_before(pack_state, term); set_input(term, stateOutputIndex + 1, pack_state); // Advance i to compensate for the term just added i++; } } } } }